📄 5_5_3.c
字号:
//6.5.3 程序清单
/************************************************************************
* 程序说明:
*
* 该程序配置UART1端口的波特率为9600,并用ADC从RP1,RP2和RP3
* 可调电位器读数,读取的数据通过串口传送去显示。
*
* 按键SW1按下时,读到的电位值开始传送;按键SW2按下时,数据传送结束。
*
************************************************************************/
#define __dsPIC30F6014__
#include <uart.h>
#include <adc12.h>
#include <p30F6014.h>
// 配置位
_FOSC(CSW_FSCM_OFF & XT_PLL4); //XT 为4xPLL 振荡器, 失效保险时钟关闭
_FWDT(WDT_OFF); //禁止看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //禁止掉电复位,使能MCLR复位
_FGS(CODE_PROT_OFF); //禁止代码保护
#define BAUDRATE 9600 //所需的波特率
#define FCY 7372800 // XTAL = 7.3728Mhz; 4 x PLL
#define SW1 !PORTAbits.RA12
#define SW2 !PORTAbits.RA13
#define LF 0x0A
#define CR 0x0D
#define NULL 0x00
#define WRITE_CHAR 0xA8
#define HOME_CLEAR 0x82
#define CURSOR_ON 0x8C
unsigned char RxValue;
void LCD_Display_Setup(void);
void LCD_Display_ClrCol(unsigned char x);
void LCD_Display_Pixel(unsigned char x,unsigned char y);
void LCD_Display_Byte(unsigned char value);
void LCD_Display_array(int *array_ptr[]);
//UART1 TX中断服务程序
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
IFS0bits.U1TXIF = 0; //清中断标志位
}
//UART1 RX中断服务程序
void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; //清中断标志位
RxValue = (char)U1RXREG; //从接收寄存器读值
LCD_Display_Byte(WRITE_CHAR); //在LCD上显示字符
LCD_Display_Byte(RxValue); //在LCD上显示接收到的值
}
void InitADC12(void);
void LoadADC(unsigned int offset);
void InitUART1(void);
void AverageADC(void);
void InitTMR3(void);
unsigned int RPValue[] = {1,2,3};
char ADCdata[] = {'R','P','1',SPACE,'=',SPACE,'1','2','3',CR,LF,
'R','P','2',SPACE,'=',SPACE,'1','2','3',CR,LF,
'R','P','3',SPACE,'=',SPACE,'1','2','3',CR,LF,
SPACE,CR,LF,NULL};
//主程序
int main(void)
{
unsigned char TxIndex;
unsigned char i;
InitTMR3(); //初始化TIMER3
InitADC12(); //初始化ADC
LCD_Display_Setup(); //初始化LCD显示
LCD_Display_Byte(HOME_CLEAR); //清LCD并把光标放到起始处
LCD_Display_Byte(CURSOR_ON); //开光标
T3CONbits.TON = 1; //打开定时器Timer3
InitUART1(); //初始化UART1
while(1)
{
TxIndex = 0;
while (!IFS0bits.ADIF); //转换完成?
IFS0bits.ADIF = 0; //清标志位
AverageADC(); //转换完成,从缓冲获取数据
for (i = 0; i<=2; i++)
LoadADC(i); //把数值放到缓冲
while (ADCdata[TxIndex]) //传送数据
{
WriteUART1((int)ADCdata[TxIndex++]);
while(BusyUART1());
}
}
}
//Timer3初始化程序,使 Timer3 每10 mS发生一次
void InitTMR3(void)
{
T3CON = 0x0010; //内部时钟Tcy/8
TMR3 = 0;
PR3 = 0x2400; //10mS时间到数值
}
//初始化ADC
void InitADC12(void)
{
ADPCFG = 0xFF8F; //所有的端口B都是数字I/O,RB6-RB4是模拟I/O
ADCON1 = 0x0044; //采用TMR3每10mSec自动转换
ADCON2 = 0x042C; //扫描输入,每12个采样中断一次
ADCSSL = 0x0070; //在引脚AN6, AN5和AN4扫描输入
ADCON3 = 0x0000F; //TMR3 = 10ms , Tad = 8Tcy = 1uS
ADCON1bits.ADON = 1; // turn ADC ON
}
//取ADC信号的平均值
void AverageADC(void)
{
RPValue[0] = ADCBUF2 + ADCBUF5 + ADCBUF8 + ADCBUFB;
RPValue[0] = RPValue[0] >> 2;
RPValue[1] = ADCBUF0 + ADCBUF3 + ADCBUF6 + ADCBUF9;
RPValue[1] = RPValue[1] >> 2;
RPValue[2] = ADCBUF1 + ADCBUF4 + ADCBUF7 + ADCBUFA;
RPValue[2] = RPValue[2] >> 2;
}
//把ADC的值放入缓冲
void LoadADC(unsigned int offset)
{
unsigned char ADCbcd;
unsigned int j;
j = offset;
offset = offset*11 + 6;
while(BusyUART1()); //等待传送完毕
ADCbcd = (char)(RPValue[j] >> 8); //转换ADC的值
if (ADCbcd > 9)
ADCbcd = ADCbcd + 0x37;
else ADCbcd = ADCbcd + 0x30;
ADCdata[offset] = ADCbcd;
ADCbcd = (char)(RPValue[j] >> 4);
ADCbcd = ADCbcd & 0x0F;
if (ADCbcd > 9)
ADCbcd = ADCbcd + 0x37;
else ADCbcd = ADCbcd + 0x30;
ADCdata[offset+1] = ADCbcd;
ADCbcd = (char)RPValue[j] & 0x0F;
if (ADCbcd > 9)
ADCbcd = ADCbcd + 0x37;
else
ADCbcd = ADCbcd + 0x30;
ADCdata[offset+2] = ADCbcd;
}
//初始化UART1
void InitUART1(void)
{
unsigned int baudvalue;
unsigned int U1MODEvalue;
unsigned int U1STAvalue;
CloseUART1();
ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR6 &
UART_TX_INT_DIS & UART_TX_INT_PR2);
U1MODEvalue = UART_EN & UART_IDLE_CON &
UART_DIS_WAKE & UART_EN_LOOPBACK &
UART_EN_ABAUD & UART_NO_PAR_8BIT &
UART_1STOPBIT;
U1STAvalue = UART_INT_TX_BUF_EMPTY &
UART_TX_PIN_NORMAL &
UART_TX_ENABLE & UART_INT_RX_CHAR &
UART_ADR_DETECT_DIS &
UART_RX_OVERRUN_CLEAR;
baudvalue = ((FCY/16)/BAUDRATE) - 1;
OpenUART1(U1MODEvalue, U1STAvalue, baudvalue);
}
//初始化SPI口,与LCD显示器通讯
void LCD_Display_Setup(void){
LATGbits.LATG9 = 1; //设SPI从引脚为高
TRISGbits.TRISG9 = 0; //设SPI引脚为输出
SPI2CON = 0x003c; //主模式, Clk = Fosc/64, 输入采样数据在输出时间中
//部,上升沿触发,时钟空闲为低
SPI2STAT = 0x8000; //使能SPI端口
}
//LCD清像素
void LCD_Display_ClrCol(unsigned char x){
unsigned char counter;
counter = 32; // 清像素点32次
while(counter > 0){
LCD_Display_Byte(0xd9); //清像素,发送命令
LCD_Display_Byte(x); //确定像素X位置,发送命令
LCD_Display_Byte(counter--); //上一个像位置,发送命令
}
}
//LCD显示像素
void LCD_Display_Pixel(unsigned char x,unsigned char y){
LCD_Display_Byte(0xd8); //设像素,发送命令
LCD_Display_Byte(x); // 确定像素X位置,发送命令
LCD_Display_Byte(y); // 确定像素Y位置,发送命令
}
//显示字节
void LCD_Display_Byte(unsigned char value){
unsigned int junk;
LATGbits.LATG9 = 1; // 设从选择为高
LATGbits.LATG9 = 0; // 设从选择为低
junk = SPI2BUF; // 读缓冲避免溢出
SPI2BUF = value; // 写数据到输出缓冲
while(!SPI2STATbits.SPIRBF); // 检查传送是否完毕
}
//LCD显示阵列
void LCD_Display_array(int *array_ptr[]){
unsigned char j,k;
for (k=0; k<122; k++)
{
j = (unsigned char)array_ptr[k]/8;
LCD_Display_ClrCol(k); // 清除下一整列
LCD_Display_Pixel(k,j); // 设置像素位置
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -