找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3772|回复: 0
打印 上一主题 下一主题
收起左侧

寝室电量提示系统(2)—下位机的设计

[复制链接]
跳转到指定楼层
楼主
ID:73735 发表于 2015-2-19 01:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 huge 于 2015-2-19 01:23 编辑

本制作程序的上位机详见:http://www.51hei.com/bbs/dpj-31601-1.html
      耗了我1个半月的时间,终于算是结束了。废话不说,直接步入正题。
       下位机的设计是以ATmega16为核心,采用时钟芯片DS1302,RS-232串行通信接口,MAX232电平转换芯片(因为在Proteus中串行接口电平已经转换了,所以并没有加入仿真中)。
/*****************************************************
【Proteus仿真效果】






  1. /*****************************************************
  2. 【CVAVR下的源程序】

  3. #include <mega16.h>

  4. #asm

  5.     .equ __ds1302_port=0x15

  6.     .equ __ds1302_io=7

  7.     .equ __ds1302_sclk=6

  8.     .equ __ds1302_rst=5

  9. #endasm

  10. #include <ds1302.h>

  11. #define uchar unsigned char

  12. uchar c0;

  13. uchar dis_buff[14],time[7];

  14. uchar roomno[50][5];

  15. int time100ms;

  16. uchar time_counter100ms,time_counter1s;

  17. uchar i,j,choice,room,roomnum,move,moveh,countnum,receivenum,sendnum;

  18. bit time100ms_ok,time1s_ok,dot0,k,key;

  19. //RSDA PORTC.1

  20. //CLK PORTC.0

  21. //RCK PORTC.2

  22. //138使能E  PORTC.4

  23. flash uchar signature[][32]={   // "以下房间电量不足",点阵16x16,长度32字节};

  24. flash uchar number[][16]={     // "0 1 2 3 4 5 6 7 8 9 ",点阵8x16,长度16字节 };

  25. flash uchar dot[][16]={            // ":"点阵8x16,长度16字节};

  26. flash uchar datachars[][16]={ // "今天是年月日",点阵8x16,长度16字节};

  27. #ifndef RXB8

  28. #define RXB8 1

  29. #endif

  30. #ifndef TXB8

  31. #define TXB8 0

  32. #endif

  33. #ifndef UPE

  34. #define UPE 2

  35. #endif

  36. #ifndef DOR

  37. #define DOR 3

  38. #endif

  39. #ifndef FE

  40. #define FE 4

  41. #endif

  42. #ifndef UDRE

  43. #define UDRE 5

  44. #endif

  45. #ifndef RXC

  46. #define RXC 7

  47. #endif

  48. #define FRAMING_ERROR (1<<FE)

  49. #define PARITY_ERROR (1<<UPE)

  50. #define DATA_OVERRUN (1<<DOR)

  51. #define DATA_REGISTER_EMPTY (1<<UDRE)

  52. #define RX_COMPLETE (1<<RXC)


  53. void sendbyteR(uchar temp) //发送数据

  54. {

  55.     uchar c;

  56.     for(c=0;c<8;c++)

  57.     {

  58.         PORTC.1=(temp)&(0x01);

  59.         temp=temp>>1;

  60.         PORTC.0=0x01; //上升沿

  61.         PORTC.0=0;

  62.     }

  63. }

  64. void time_to_disbuffer()    // 日期、时钟、天数送显示缓冲区函数

  65. {

  66.     unsigned char i,j0=0;

  67.     for (i=0;i<=6;i++)

  68.     {

  69.         dis_buff[j0++] = time[i]%10;

  70.         dis_buff[j0++] = time[i]/10;

  71.     }

  72. }

  73. uchar s,chartemp[10];

  74. flash unsigned char *disword[36];

  75. void disdata()         //字幕缓冲函数

  76. {

  77.     uchar i;

  78.     for(i=0;i<=7;i++) disword[i]=&number[1][0];

  79.     for(i=8;i<=13;i++) disword[i]=&datachars[i-8][0];

  80.     for(i=14;i<=17;i++) disword[i]=&number[2*dis_buff[27-i]][0];

  81.     disword[18]=&datachars[6][0];

  82.     disword[19]=&datachars[7][0];

  83.     disword[20]=&number[2*dis_buff[9]][0];

  84.     disword[21]=&number[2*dis_buff[8]][0];

  85.     disword[22]=&datachars[8][0];

  86.     disword[23]=&datachars[9][0];

  87.     disword[24]=&number[2*dis_buff[7]][0];

  88.     disword[25]=&number[2*dis_buff[6]][0];

  89.     disword[26]=&datachars[10][0];

  90.     disword[27]=&datachars[11][0];

  91.     disword[28]=&number[1][0];

  92.     disword[29]=&number[2*dis_buff[5]][0];

  93.     disword[30]=&number[2*dis_buff[4]][0];  

  94.     disword[31]=&dot[0][0];

  95.     disword[32]=&number[2*dis_buff[3]][0];

  96.     disword[33]=&number[2*dis_buff[2]][0];

  97.     disword[34]=&number[1][0];

  98.     disword[35]=&number[1][0];  

  99. }

  100. void move_left()          //字幕左移函数

  101. {

  102. uchar i;

  103.         for(i=0;i<=9;i++)

  104.    chartemp[i] = *(disword[i+s]+j);

  105. for(i=0;i<=8;i++)

  106.    chartemp[i]=(chartemp[i]<<moveh)|(chartemp[i+1]>>(8-moveh));

  107. }

  108. void todispcase3()

  109. {

  110.     choice=3;

  111.     if(time100ms_ok)

  112.     {

  113.         time100ms_ok=0;

  114.         if(++moveh>=8)

  115.         {

  116.             moveh=0;

  117.             if(++s>=27) s=0;

  118.         }

  119.     }

  120.     if(time1s_ok)

  121.     {

  122.         time1s_ok=0;

  123.         rtc_get_date(&time[3],&time[4],&time[5]);

  124.         rtc_get_time(&time[2],&time[1],&time[0]);

  125.         time_to_disbuffer();

  126.         disdata();     

  127.     }

  128. }

  129. void display(uchar diff)  //扫描显示函数

  130. {

  131.     PORTC.4=0;

  132.     switch(diff)

  133.     {

  134.         case 0:        //显示时间(小时,分)

  135.         {

  136.             sendbyteR(number[1][j]);

  137.             sendbyteR(number[1][j]);

  138.             sendbyteR(number[dis_buff[2]*2][j]);

  139.             sendbyteR(number[dis_buff[3]*2][j]);

  140.             if(dot0) sendbyteR(dot[0][j]);

  141.             else sendbyteR(number[1][j]);

  142.             sendbyteR(number[dis_buff[4]*2][j]);

  143.             sendbyteR(number[dis_buff[5]*2][j]);

  144.             sendbyteR(number[1][j]);      

  145.             break;

  146.         }

  147.         case 1:       //显示缺电提示字幕

  148.         {   

  149.             sendbyteR(signature[3+4*k][j*2+1]);

  150.             sendbyteR(signature[3+4*k][j*2]);

  151.             sendbyteR(signature[2+4*k][j*2+1]);

  152.             sendbyteR(signature[2+4*k][j*2]);

  153.             sendbyteR(signature[1+4*k][j*2+1]);

  154.             sendbyteR(signature[1+4*k][j*2]);

  155.             sendbyteR(signature[0+4*k][j*2+1]);

  156.             sendbyteR(signature[0+4*k][j*2]);

  157.             break;   

  158.         }

  159.         case 2:       //显示缺电寝室号

  160.         {  

  161.             sendbyteR(number[1][j]);

  162.             sendbyteR(number[(roomno[room][4])*2][j+move]);

  163.             sendbyteR(number[(roomno[room][3])*2][j+move]);

  164.             sendbyteR(number[(roomno[room][2])*2][j+move]);

  165.             sendbyteR(number[(roomno[room][1])*2][j+move]);

  166.             sendbyteR(number[(roomno[room][0])*2][j+move]);

  167.             sendbyteR(number[1][j]);

  168.             sendbyteR(number[1][j]);

  169.             break;

  170.         }

  171.         case 3:      //左移显示时间(年,月,日,小时,分)

  172.         {

  173.             move_left();

  174.             sendbyteR(chartemp[7]);

  175.             sendbyteR(chartemp[6]);

  176.             sendbyteR(chartemp[5]);

  177.             sendbyteR(chartemp[4]);

  178.             sendbyteR(chartemp[3]);

  179.             sendbyteR(chartemp[2]);

  180.             sendbyteR(chartemp[1]);

  181.             sendbyteR(chartemp[0]);   

  182.             break;

  183.         }            

  184.     }

  185.     PORTA=j;

  186.     PORTC.2=1;

  187.     PORTC.2=0;  

  188.     PORTC.4=1;

  189.     if(++j>=16) j=0;

  190. }

  191. // USART Receiver buffer

  192. #define RX_BUFFER_SIZE 11

  193. #define UART_BEGIN_STX 0xBB

  194. #define UART_END_STX   0xEE

  195. char rx_buffer[RX_BUFFER_SIZE];

  196. #if RX_BUFFER_SIZE <= 256

  197. unsigned char rx_wr_index,rx_rd_index,rx_counter;

  198. #else

  199. unsigned int rx_wr_index,rx_rd_index,rx_counter;

  200. #endif

  201. // This flag is set on USART Receiver buffer overflow

  202. bit rx_buffer_overflow;

  203. // USART Receiver interrupt service routine

  204. interrupt [USART_RXC] void usart_rx_isr(void)

  205. {

  206.     char status,data;

  207.     status=UCSRA;

  208.     data=UDR;

  209.     if(!rx_buffer_overflow)

  210.     {

  211.         if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

  212.         {

  213.             rx_buffer[rx_wr_index]=data;

  214.             rx_wr_index++;

  215.             switch(rx_wr_index)

  216.             {

  217.                 case 1:     // 检验起始字符

  218.                     if (data != UART_BEGIN_STX)

  219.                         rx_wr_index = 0;

  220.                     break;

  221.                 case 10:

  222.                     if (data !=(rx_buffer[1]^rx_buffer[4]))

  223.                         rx_wr_index = 0;

  224.                     break;

  225.                 case 11:

  226.                     rx_wr_index=0;

  227.                     if (data == UART_END_STX) rx_buffer_overflow=1;

  228.                     break;   

  229.             }

  230.         }

  231.     }

  232. }

  233. #ifndef _DEBUG_TERMINAL_IO_

  234. // Get a character from the USART Receiver buffer

  235. #define _ALTERNATE_GETCHAR_

  236. #pragma used+

  237. char getchar(void)

  238. {

  239. char data;

  240. while (rx_counter==0);

  241. data=rx_buffer[rx_rd_index++];

  242. #if RX_BUFFER_SIZE != 256

  243. if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;

  244. #endif

  245. #asm("cli")

  246. --rx_counter;

  247. #asm("sei")

  248. return data;

  249. }

  250. #pragma used-

  251. #endif

  252. // USART Transmitter buffer

  253. #define TX_BUFFER_SIZE 11

  254. char tx_buffer[TX_BUFFER_SIZE];

  255. #if TX_BUFFER_SIZE <= 256

  256. unsigned char tx_wr_index,tx_rd_index,tx_counter;

  257. #else

  258. unsigned int tx_wr_index,tx_rd_index,tx_counter;

  259. #endif

  260. // USART Transmitter interrupt service routine

  261. interrupt [USART_TXC] void usart_tx_isr(void)

  262. {

  263.     if (tx_counter)

  264.     {

  265.         --tx_counter;

  266.         UDR=tx_buffer[tx_rd_index++];

  267.         #if TX_BUFFER_SIZE != 256

  268.         if (tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;

  269.         #endif

  270.     }

  271. }

  272. #ifndef _DEBUG_TERMINAL_IO_

  273. // Write a character to the USART Transmitter buffer

  274. #define _ALTERNATE_PUTCHAR_

  275. #pragma used+

  276. void putchar(char c)

  277. {

  278.     while (tx_counter == TX_BUFFER_SIZE);

  279.     #asm("cli")

  280.     if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))

  281.     {

  282.         tx_buffer[tx_wr_index++]=c;

  283.         #if TX_BUFFER_SIZE != 256

  284.         if (tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;

  285.         #endif

  286.         ++tx_counter;

  287.     }

  288.     else

  289.         UDR=c;

  290.     #asm("sei")

  291. }

  292. #pragma used-

  293. #endif

  294. // Standard Input/Output functions

  295. #include <stdio.h>

  296. // Timer 0 output compare interrupt service routine

  297. interrupt [TIM0_COMP] void timer0_comp_isr(void)

  298. {

  299. // Place your code here

  300.     display(choice);            //定时2ms,2ms显示扫描一次   

  301.     if(++time_counter100ms>=50)

  302.     {

  303.         time_counter100ms=0;    //定时100ms

  304.         time100ms_ok=1;

  305.         time100ms++;

  306.         if(++time_counter1s>=10)

  307.         {

  308.             time_counter1s=0;

  309.             time1s_ok=1;    //定时1s

  310.             dot0=~dot0;     //秒闪烁

  311.         }

  312.     }

  313. }

  314. void main(void)         //主函数

  315. {

  316. PORTA=0x00;

  317. DDRA=0x0F;

  318. PORTC=0x00;

  319. DDRC=0xF7;

  320. PORTD=0x00;

  321. DDRD=0x02;


  322. // Mode: CTC top=OCR0

  323. TCCR0=0x0B;   // Timer/Counter 0 initialization

  324. TCNT0=0x00;  // Clock source: System Clock

  325. OCR0=0x7C;   // Clock value: 62.500 kHz


  326. // USART initialization

  327. UCSRA=0x00;

  328. UCSRB=0xD8;    // Communication Parameters: 8 Data, 1 Stop, No Parity

  329. UCSRC=0x86;     // USART Receiver: On,USART Transmitter: On

  330. UBRRH=0x00;    // USART Mode: Asynchronous

  331. UBRRL=0x19;    // USART Baud Rate: 9600

  332. countnum=0;

  333. roomnum=0;   //roomnum为要显示寝室的个数

  334. room=0;

  335. move=0;

  336. rtc_init(1,2,3);   // 初始化DS1302

  337. //rtc_get_time(&time[2],&time[1],&time[0]);

  338. time[6]=20;time[5]=12;time[4]=11;time[3]=12;

  339. time[2]=0;time[1]=0;time[0]=0;

  340. time_to_disbuffer();

  341. disdata();

  342. choice=0;

  343. // Global enable interrupts

  344. #asm("sei")

  345. while (1)

  346.       {

  347.       // Place your code here

  348.         if (rx_buffer_overflow)

  349.         {                       // 有刚接收到数据包需要处理

  350.         receive:

  351.             PORTC.4=0;   

  352.             switch(rx_buffer[1])

  353.             {

  354.                 case 0xA2:

  355.                     for(i=2;i<=8;i++)

  356.                         time[8-i]=rx_buffer[i];

  357.                     countnum=1;

  358.                     break;

  359.                 case 0xA8:

  360.                     for(i=2;i<=6;i++)

  361.                         roomno[roomnum][i-2]=rx_buffer[i];  

  362.                     roomnum++;

  363.                     break;

  364.                 case 0xAF:

  365.                     receivenum=rx_buffer[2];

  366.                     TIMSK=0x00;

  367.                     time100ms=0;

  368.                     choice=0;

  369.                     room=0;

  370.                     move=0;

  371.                     countnum=0;

  372.                     roomnum=0;

  373.                     s=0;

  374.                     moveh=0;

  375.                     time100ms=0;

  376.                     break;

  377.                 default:

  378.                     sendnum=0x01;

  379.                     break;        

  380.             }

  381.             rx_buffer_overflow = 0;          // 允许接收下一个数据包                  

  382.         }

  383.         

  384.         if(((countnum+roomnum)==receivenum)&(receivenum>0))

  385.         {

  386.             sendnum=0x00;

  387.             putchar(UART_BEGIN_STX);

  388.             putchar('AA');

  389.             putchar(sendnum);

  390.             for(c0=0;c0<=5;c0++) putchar('00');

  391.             putchar('AA');

  392.             putchar(UART_END_STX);

  393.             TIMSK=0x02;

  394.         }

  395.         

  396.         if(roomnum>0) key=1;

  397.         else key=0;

  398.         rtc_set_date(time[3],time[4],time[5]);

  399.         rtc_set_time(time[2],time[1],time[0]);

  400.         time_to_disbuffer();

  401.         //显示模块处理

  402.         //while((countnum+roomnum)==receivenum)

  403.         while(((countnum+roomnum)==receivenum)&(receivenum>0))

  404.         {

  405.             if(rx_buffer_overflow) goto receive; //判断是否更新显示信息

  406.             if(key)           //显示缺电提示判断

  407.             {   

  408.                 if(time100ms<=210)

  409.                 {

  410.                     todispcase3();

  411.                 }

  412.                 else if(time100ms<=280)

  413.                 {

  414.                     choice=0;

  415.                     if(time1s_ok)

  416.                     {   

  417.                         time1s_ok=0;

  418.                         rtc_get_time(&time[2],&time[1],&time[0]);

  419.                         time_to_disbuffer();

  420.                     }

  421.                 }            //显示现在时间

  422.                 else if(time100ms<=290)

  423.                 {

  424.                     k=0;

  425.                     choice=1;

  426.                 }           //显示“以下房间”

  427.                 else if(time100ms<=300)

  428.                 {   

  429.                     k=1;

  430.                     choice=1;   

  431.                 }          //显示“电量不足”

  432.                 else

  433.                 {

  434.                     choice=2;

  435.                     if(time100ms_ok)

  436.                     {

  437.                         time100ms_ok=0;

  438.                         if(++move>=16)

  439.                         {

  440.                             move=0;

  441.                             if(++room>=roomnum)

  442.                             {

  443.                                 room=0;

  444.                                 s=0;

  445.                                 moveh=0;

  446.                                 time100ms=0;

  447.                                 time100ms_ok=0;

  448.                             }

  449.                         }      

  450.                     }    //显示“缺电寝室”,1.6s换一个寝室号

  451.                 }

  452.             }

  453.             else

  454.             {

  455.                 if(time100ms<=210)    //只显示现在时间

  456.                 {

  457.                     todispcase3();

  458.                 }

  459.                 else if(time100ms<=3810)

  460.                 {

  461.                     choice=0;

  462.                     if(time1s_ok)

  463.                     {   

  464.                         time1s_ok=0;

  465.                         rtc_get_time(&time[2],&time[1],&time[0]);

  466.                         time_to_disbuffer();

  467.                     }

  468.                 }

  469.                 else

  470.                 {

  471.                     s=0;

  472.                     moveh=0;

  473.                     time100ms=0;

  474.                     time100ms_ok=0;

  475.                 }

  476.             }

  477.         }

  478.       }
  479. }  

复制代码
/*****************************************************
最后效果怎么说呢,感觉在Proteus仿真中的时间会慢一点,1s并不是所谓的1s,在显示模式的切换下也有一定的BUG。很想入手个二手的点阵屏,看看真实的效果怎样,进一步修改。呵呵。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表