本帖最后由 wspytu 于 2013-12-2 18:18 编辑
试用MEGA1284P开发板终极目标是:MCU驱动8位8段数码管,显示时间、日期、温度等信息,通过上位机或15键无线遥控控制数码管显示模式,或修改当前时间或日期。 具体方案如下:MCU使用3个GPIO引脚以串转并方式通过74HC244驱动8位数码管;通过16位TIMER1计数CTC模式计时;上位机软件通过串口控件向MCU发送控制信息,对应无线遥控,上位机界面也包含15个按键;15键无线遥控包含0-9按键值、功能键、左移、右移、确认、取消键,MCU模拟PT2262解码,通过采集无线接受模块数据引脚信息,判断按键值,功能键控制数码管显示模式,0-9按键值调整当前时间或日期,其他键为辅助功能。 MEGA1284P试用板、数码管显示板、无线遥控模块整体如下图所示:
15键无线遥控发送和接收模块:
本篇帖子只实现了MCU控制部分,无线解码还没有调试,上位机软件只实现了部分界面,不过通过串口调试助手发送相应指令,控制数码管显示功能已实现(注:串口通讯没有添加校验)。通讯协议如下: 时间数组,上位机调整时间或日期时发送,MCU每隔5s主动发送 00 0A 13 11 1E 08 1E 00 00 58 0) 00 功能码 1) 0A 总字节长度 2-4) 13 11 1E 年月日 5-7) 08 1E 00 时分秒 8) 00 100ms值,从0-10 9) 58 结束符,Xplan X=0X58
按键控制,上位机发送,MCU接收后再返回 00 04 00 58 0) 00 功能码 1) 04 总字节长度 2) 00 按键值,范围00-0E,00-09代表0-9数值,0A表示功能键,0B左移,0C右移,0D确认,0E取消 3) 58 结束符
温度,数码管显示模式为温度时,MCU主动发送给上位机 00 06 01 02 0058 0) 00 功能码 1) 06 总字节长度 2-4) 01 02 00 温度值,分别为温度十位、个位、小数位 5) 58 结束符
数码管显示图片如下,默认上电时间为08:30:00,日期13-11-30:
部分代码如下: 注意事项、变量和数组定义如下: //13年11月30日
//NTC温度ADC,908对应2.27v 25度(基准电压2.56),最高温度约28.2
//USART1接受按键数值,每隔200ms判断一次按键
//USART1接受使用中断模式,发送不占用中断,TXCIE1=0
//定义数组长度时,一定要实际长度+1个结束符(数码管显示,数组长度原定义10个字节,数码管显示'9'不正常)
/* 数码管驱动,0点亮,1灭,带小数点,位控制序列如下 -7- |2 |6 -1- |3 |5 -4- .0 */
//LED 顺时针方向ED0-PB0 LED2-PB1 LED3-PB2 LED1-PB3 //LED接上拉电阻,低电平点亮;引脚配置为输出时,向PINX对应引脚写入1,会自动翻转TOGGLING引脚电平
#include "avr_compiler.h"
#define ADC_NUM_OVERSAMPLING 16
enum adc_sources { FILTER_OUTPUT= 0x05, //!<RC filter on ADC Channel 5, PA5 LIGHT_SENSOR= 0x06, //!<Light Sensor on ADC Channel 6, PA6 NTC= 0x07 //!< NTCsensor on ADC Channel 7, PA7 };
static volatile bool Time1s_flag=0; static volatile bool Send_flag=0; static volatile bool KeySet_flag=0;
static volatile bool Disflash_flag=0; //按下设置标志位,按下确认清零 static volatile bool DisEn_flag=0; //数码管显示允许标志位,数码管正常显示1分钟后关闭
static volatile bool Temp_Rdflag=0; //读当前温度标志位
static volatile unsigned charTime10ms_cnt=0; //定时10ms计数变量 static volatile unsigned char Rx1_cnt=0; //串口接受字节计数变量 static volatile unsigned char Send_len=0; //串口接受字节计数变量 static volatile unsigned charKeySet_value=0; //串口发送按键值
unsigned char Setup_Value=0; //功能设置计数变量 unsigned char DI_Flash=0; unsigned char Disflash_cnt=0; unsigned char DisEn_cnt=0; unsigned char DI_A=0; unsigned char DI_B=0; unsigned char DI_C=0; unsigned char Keyin_cnt=0; //6位数码管输入按键值计数变量 unsigned int Temp_value=0; //当前温度*10,避免小数位
//数码管显示数组0-9 const unsigned charClock_Display[16]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09};
static volatile unsigned charTimeBuf[8]={13,11,30,8,30,0};
static volatile unsigned charRx1_buf[32]={0}; //串口接收数组 static volatile unsigned charTx1_buf[32]={0}; //串口发送数组
unsigned char Keyin_buf[7]={0}; //6位数码管按键调整值
MCU GPIO、TIMER1、USART1、ADC初始化,可参考官方例程,只是串口使用接收中断方式;温度读取程序参考官方例程;数码管显示和按键处理部分程序代码较多,感兴趣的可以查看附件。
串口发送程序如下: void usart1_send(volatile unsigned charbuf[],volatile unsigned char len) { unsignedchar i;
for(i=0;i<len;i++) { UCSR1A |= (1 << TXC1); while(!(UCSR1A & (1 <<UDRE1))); // Waitfor empty transmit buffer UDR1= buf; } } 主函数处理程序如下: int main(void) { volatileunsigned char i;
mega1284p_init();
DisEn_flag= 1; DisEn_cnt= 0;
while(1) { if(Time1s_flag) { Time1s_flag= 0;
Time_Process();
if((TimeBuf[5]% 2) == 0) PORTB|= 0x01; else PORTB&= 0xfe;
Time_Display();
if((TimeBuf[5]% 5) == 0) { for(i=0;i<6;i++) { Tx1_buf[i+2]= TimeBuf; } Tx1_buf[8]= Time10ms_cnt; Send_flag= 1; Send_len= 10; } if(DisEn_flag) { DisEn_cnt++; if(DisEn_cnt> 60) { DisEn_cnt= 0; DisEn_flag= 0; Disflash_flag= 0; Setup_Value= 0; DI_Flash= 0; } if(Disflash_flag) { Disflash_cnt++; if(Disflash_cnt> 20) //超过20s没有按确认键自动取消 { Disflash_cnt= 0; Disflash_flag= 0; Setup_Value= 0; DI_Flash= 0; } } } } if(Send_flag) { Send_flag= 0; Tx1_buf[0]= 0; Tx1_buf[1]= Send_len; Tx1_buf[Send_len-1]= 0x58; //结束符 usart1_send(Tx1_buf,Send_len); } if(KeySet_flag) { KeySet_flag= 0; Key_Scan(); } if(Temp_Rdflag) { Temp_Rdflag= 0; read_ntc(); Tx1_buf[2]= Temp_value / 100; Tx1_buf[3]= (Temp_value % 100) / 10; Tx1_buf[4]= Temp_value % 10; Send_flag= 1; Send_len= 6; } } } TIEMR1中断程序如下; ISR(TIMER1_COMPA_vect) //TIMER1CTC中断 { Time10ms_cnt++; if(Time10ms_cnt>= 100) { Time10ms_cnt= 0; Time1s_flag= 1; } } 串口接收中断程序如下,MCU接收到时间数组、按键数组后,向上位机返回接收到的数组: ISR(USART1_RX_vect) //USART1 RX中断 { unsignedchar i; unsignedchar Rx_ch=0; Rx_ch= UDR1; if(Rx1_cnt== 0) { if(Rx_ch== 0) { Rx1_buf[Rx1_cnt]= Rx_ch; Rx1_cnt++; } } else { Rx1_buf[Rx1_cnt]= Rx_ch; Rx1_cnt++; if(Rx1_cnt> 30) Rx1_cnt= 0; if(Rx1_cnt== Rx1_buf[1]) { Rx1_cnt= 0; if((Rx1_buf[1]== 0x0A) &&(Rx1_buf[9] == 0x58)) { for(i=0;i<6;i++) { TimeBuf= Rx1_buf[i+2];
Tx1_buf[i+2]= Rx1_buf[i+2]; } Time10ms_cnt= Rx1_buf[8];
Send_flag= 1; Send_len= 10; } elseif((Rx1_buf[1] == 0x04) && (Rx1_buf[3] == 0x58)) { if(Rx1_buf[1]< 16) //15个按键 { KeySet_flag= 1; KeySet_value= Rx1_buf[2]; Tx1_buf[2]= Rx1_buf[2];
Send_flag= 1; Send_len= 4; } } } } }
file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image004.jpg
移位数码管闪烁如下:
file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image006.jpg
日期数码管闪烁如下:
file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image008.jpg
通过串口调试,更改为当前时间,15:24:00,数码管显示如下: file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.jpg
温度显示,长沙12月1日下午温度为10度(温度读取有误差,有一次看到时12.2度)中间小点不亮,可能是硬件没有控制小点位,数码管显示如下:
因为用同事手机拍摄,这张照片没有拷过来,大家就见谅吧
VB编写的上位机部分界面如下(在长沙到深圳高铁路上截的图片):
第1次自己写VB程序,进程有点慢,还没进行调试。
整个工程如下,所有处理都写在main.c文件,没有分类,请大家不要介意;程序编写不严谨,仅供参考: |