找回密码
 立即注册

QQ登录

只需一步,快速开始

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

atmega16单片机设计电子考试系统Proteus仿真及源程序

[复制链接]
跳转到指定楼层
楼主
  •      功能用途:采用两个单片机系统实现四则运算考试及判卷功能,具体内容包括:
⑴两个单片机系统分别作为服务器和答题终端。服务器负责验证考生个人信息,发送试题到终端,定时收卷及判分功能。答题终端负责输入考生个人信息,答题,修改答案及传送答案到服务器。
⑵服务器验证考生个人信息,若信息不正确则向终端发出提示信息。信息验证正确后将试题发送到答题终端,同时开始计时。无论答题是否完成,考试时间到则强制收题。也可在考试时间尚有剩余时接收答题终端发送过来的答案。收题后进行判分工作并给出最终得分及答题情况统计信息。对回答错误的题目则给出原题及正确答案。
⑶答题终端在收到试题后向考生显示试题内容(可逐道显示)并接受考生输入的答案。试题显示应具备翻页功能以允许考生反复浏览试题或检查所作答案。当考生检查完毕且考试时间尚有剩余,允许考生向服务器发送最终答案。
⑷实现服务器和答题终端的两个单片机系统均应包含键盘和LCD液晶显示模块。两个单片机系统通过串口进行通信。
机系统通过串口进行通信。
  • 验收要求及说明
⑴给出使用说明,包括按键的定义,操作方法等。
⑵所有功能用途均可实现且各功能转换正常(模拟5道题即可)。
⑶考生个人信息包括考生姓名(可用拼音表示)和6位的学号。
⑷验收时需要演示考生个人信息不正确时的处理情况;
⑸服务器和终端都应实时显示考试剩余时间;
⑹四则运算应覆盖加减乘除四种运算;
⑺终端答题时,在未提交答案前应允许反复浏览或修改答案
  • 整体设计电路图展示


  • 模块展示
  • 终端部分展示
终端的atmega16单片机电路连接如图所示。复位端口连一个上拉电阻,下接一个按键,按键按下时,终端单片机复位,能使终端的显示屏回到初始的界面。在引脚XTAL1和XTAL2上外接石英晶体和电容组成的谐振回路,配合片内的OSC振荡电路构成振荡源。
终端的显示屏设计如图所示,里面有预置的姓名和学号,只有当服务器输入的和终端预置的一致时才能进入系统。
终端的初始页面
通过验证进入系统后终端会开始计时并  答题结束之后,终端会显示正确和错误的题目个数
显示剩余时间,如果验证失败则保持初  在时间规定内,考生可自己提交答案。超出时间的
始页面不变。                        话,则系统强制收卷
  • 客户段部分展示
客户端单片机与终端单片机有相似的地方的这里不做赘述。
客户端键盘展示
键盘完成输入姓名学号、答题功能。旁边还有四个按键,可以实现在答题的时候,上下翻查看题目,答题有误的情况下清除原有答案,和作答完毕时提交答案的功能。
客户端功能展示
初始页面如图所示,要求输入姓名学号,输入有误则会显示“有一个错误,请重新输入”
输入正确则会进入考试系统
显示考试开始,计时并显示剩余的时间。这里我们准备了5道题目,按上下键可以翻动题目清除可以清除答案
考试结束服务端会显示正确和错误的题目个数。
此时按上下键可以查看所有题目和答案
  • 程序代码展示


单片机源程序如下:

用户端
  1. #include <mega16.h>
  2. #include <delay.h>

  3. #define BAUD    9600    // 波特率采用9600bps
  4. #define CRYSTAL 4000000 // 系统时钟8MHz

  5. #define BIT0 0X01
  6. #define BIT1 0X02
  7. #define BIT2 0X04
  8. #define BIT3 0X08
  9. #define BIT4 0X10
  10. #define BIT5 0X20
  11. #define BIT6 0X40
  12. #define BIT7 0X80

  13. unsigned char const BIT[]={BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7};

  14. //计算和定义波特率设置参数
  15. #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率计算
  16. #define BAUD_H (unsigned char)(BAUD_SETTING>>8) // 高8位
  17. #define BAUD_L (unsigned char)(BAUD_SETTING) // 低8位

  18. unsigned char const num_str[]={"0123456789"};
  19. void USART_INIT(void);
  20. void USART_SEND(unsigned char data); // USART发送子程序
  21. interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中断服务
  22. void lcd_gpio_init(void);
  23. void LcdInitiate(void);
  24. void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p);
  25. void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign);
  26. void KEY_INIT(void);
  27. void KEY_CHECK(void);
  28. void key(void);
  29. unsigned char input_buf[16],input_cnt = 0;
  30. unsigned char timu_buf[5][16],daan_buf[5][2];
  31. unsigned char flag_steep = 0,rx_buf[16],rx_cnt=0,rx_cnt_r=0;
  32. unsigned char timu_pos = 0;
  33. unsigned char lcd_buf[16],lcd_cnt=0;
  34. void main( void )
  35. {
  36.     unsigned char dat=0,i,lcd_buf[16],lcd_cnt;
  37.     unsigned int  tim_cnt = 0,t = 0;
  38.     KEY_INIT();
  39.     USART_INIT();
  40.     lcd_gpio_init();
  41.     LcdInitiate();
  42.     LCD1602_string(1,1,"Your Name:");
  43.     LCD1602_string(2,1,"Your Num:");
  44.     #asm("sei") // 开中断
  45.     flag_steep = 0;
  46.     while(1)
  47.     {   
  48.         delay_ms(1);
  49.         key();
  50.         KEY_CHECK();  
  51.         if(flag_steep==0)//输入考生信息
  52.         {   
  53.             if(input_cnt<=3)
  54.             {
  55.                 lcd_cnt = 0;
  56.                 for(i=0;i<input_cnt;i++)
  57.                 {
  58.                     lcd_buf[lcd_cnt++] = input_buf[i];
  59.                 }
  60.                 lcd_buf[lcd_cnt++] = 0;
  61.                 //LCD1602_string(1,11,"      \0");
  62.                 LCD1602_string(1,11,lcd_buf);
  63.             }
  64.             else if(input_cnt>3&&input_cnt<=9)
  65.             {
  66.                 lcd_cnt = 0;
  67.                 for(i=0;i<(input_cnt-3);i++)
  68.                 {
  69.                     lcd_buf[lcd_cnt++] = input_buf[i+3]+'0';  
  70.                 }
  71.                 lcd_buf[lcd_cnt++] = 0;
  72.                 LCD1602_string(2,10,lcd_buf);
  73.                 if(input_cnt==9)
  74.                 {   
  75.                     input_cnt = 0;
  76.                     lcd_cnt = 0;
  77.                     lcd_buf[lcd_cnt++] = 0x00;//发送考生信息
  78.                     for(i=0;i<9;i++)lcd_buf[lcd_cnt++] = input_buf[i];
  79.                     for(i=0;i<10;i++)USART_SEND(lcd_buf[i]);   
  80.                 }
  81.             }           
  82.         }
  83.         else if(flag_steep==1)
  84.         {
  85.             if(t<1000)t++;
  86.             else
  87.             {
  88.                 t= 0;
  89.                 tim_cnt--;
  90.                 lcd_cnt = 0;
  91.                 lcd_buf[lcd_cnt++] = 0x01;//发送剩余时间
  92.                 lcd_buf[lcd_cnt++] = tim_cnt/60;//发送剩余分钟
  93.                 lcd_buf[lcd_cnt++] = tim_cnt%60;//发送剩余秒钟   
  94.                 for(i=0;i<3;i++)USART_SEND(lcd_buf[i]);
  95.                 LCD1602_string(1,1,"Time left:");
  96.                 lcd_cnt = 0;
  97.                 lcd_buf[lcd_cnt++] = tim_cnt/60/10%10+'0';
  98.                 lcd_buf[lcd_cnt++] = tim_cnt/60%10+'0';
  99.                 lcd_buf[lcd_cnt++] = ':';
  100.                 lcd_buf[lcd_cnt++] = tim_cnt%60/10%10+'0';
  101.                 lcd_buf[lcd_cnt++] = tim_cnt%60%10+'0';
  102.                 lcd_buf[lcd_cnt++] = 0;
  103.                 LCD1602_string(1,11,lcd_buf);
  104.                 if(tim_cnt==0)
  105.                 {
  106.                     flag_steep = 2;
  107.                     LCD1602_string(2,1,"The exam is over\0");
  108.                 }
  109.             }
  110.         }
  111.         if(rx_cnt)
  112.         {
  113.             if(rx_cnt == rx_cnt_r)
  114.             {   
  115.                 if(rx_cnt==16)
  116.                 {
  117.                     for(i=0;i<15;i++)
  118.                     {
  119.                         timu_buf[rx_buf[0]-2][i] = rx_buf[i+1];
  120.                     }
  121.                     LCD1602_string(2,1,"                \0");
  122.                     for(i=0;i<13;i++)lcd_buf[i] = timu_buf[0][i];
  123.                     lcd_buf[i] = 0;
  124.                     LCD1602_string(2,1,lcd_buf);        
  125.                 }
  126.                 else if(rx_buf[0]==0x00&&rx_buf[1]==0x01&&rx_cnt==2)
  127.                 {
  128.                     LCD1602_string(1,1,"                \0");
  129.                     LCD1602_string(2,1,"                \0");
  130.                     LCD1602_string(1,1,"There is an Err!\0");
  131.                     LCD1602_string(2,1,"Please Again !  \0");
  132.                     delay_ms(1000);
  133.                     LCD1602_string(1,1,"                \0");
  134.                     LCD1602_string(2,1,"                \0");
  135.                     LCD1602_string(1,1,"Your Name:");
  136.                     LCD1602_string(2,1,"Your Num:");
  137.                     input_cnt = 0;        
  138.                 }
  139.                 else if(rx_buf[0]==0x01&&rx_cnt==3)//收到开始考试指令
  140.                 {
  141.                     tim_cnt =  rx_buf[1];
  142.                     tim_cnt =  tim_cnt*60 + rx_buf[2];
  143.                     flag_steep = 1;
  144.                     t = 0;
  145.                     LCD1602_string(1,1," lets start              \0");
  146.                     LCD1602_string(2,1," the exam              \0");
  147.                 }
  148.                 rx_cnt = 0;
  149.             }
  150.             rx_cnt_r = rx_cnt;
  151.         }
  152.     }
  153. }


  154. void input_dat(unsigned char dat)
  155. {
  156.     unsigned char i;
  157.     if(flag_steep==0&&input_cnt<3&&(dat>='A'&&dat<='F'))
  158.     {
  159.         input_buf[input_cnt++] = dat;         
  160.     }
  161.     else if(flag_steep==0&&input_cnt>=3&&input_cnt<9&&(dat>=0&&dat<=9))
  162.     {
  163.         input_buf[input_cnt++] = dat;         
  164.     }
  165.     else if(flag_steep==1&&input_cnt<2&&(dat>=0&&dat<=9))
  166.     {   
  167.         if(input_cnt==0)
  168.         {
  169.             for(i=0;i<2;i++)daan_buf[timu_pos][i]=' ';
  170.         }
  171.         daan_buf[timu_pos][input_cnt++] = dat+'0';
  172.         if(input_cnt==2)input_cnt = 0;
  173.         LCD1602_string(2,14,"   \0");
  174.         for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
  175.         lcd_buf[i] = 0;
  176.         LCD1602_string(2,14,lcd_buf);
  177.     }
  178. }
  179. interrupt [USART_RXC] void USART_RCV_INT(void) // USART接收中断服务
  180. {
  181.     unsigned char data;
  182.     data = UDR; // 接收数据
  183.     if(rx_cnt<16)
  184.     {
  185.         rx_buf[rx_cnt++] = data;
  186.     }
  187. }
  188. /**************KEY*************************/
  189. void KEY_INIT(void)
  190. {
  191.     PORTC = 0xF0; //输出
  192.     DDRC  = 0x0F; //输入,上拉有效
  193.     PORTB |= 0x0F;
  194.     DDRB  &= 0xF0;
  195. }
  196. void KEY_CHECK(void)
  197. {   
  198.     unsigned char i,j,k;
  199.     if((PINB&0x01)==0) //+
  200.     {
  201.         if(timu_pos<4)timu_pos++;
  202.         else timu_pos = 0;
  203.         if(flag_steep==1)
  204.         {
  205.             LCD1602_string(2,1,"                \0");
  206.             for(i=0;i<13;i++)lcd_buf[i] = timu_buf[timu_pos][i];
  207.             lcd_buf[i] = 0;
  208.             LCD1602_string(2,1,lcd_buf);
  209.             LCD1602_string(2,14,"   \0");
  210.             for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
  211.             lcd_buf[i] = 0;
  212.             LCD1602_string(2,14,lcd_buf);   
  213.         }
  214.         else if(flag_steep==2)
  215.         {
  216.             LCD1602_string(2,1,"                \0");
  217.             for(i=0;i<15;i++)lcd_buf[i] = timu_buf[timu_pos][i];
  218.             lcd_buf[i] = 0;
  219.             LCD1602_string(2,1,lcd_buf);        
  220.         }
  221.         while((PINB&0x01)==0);
  222.     }
  223.     else if((PINB&0x02)==0) //-
  224.     {
  225.         if(timu_pos>0)timu_pos--;
  226.         else timu_pos = 4;
  227.         if(flag_steep==1)
  228.         {
  229.             LCD1602_string(2,1,"                \0");
  230.             for(i=0;i<13;i++)lcd_buf[i] = timu_buf[timu_pos][i];
  231.             lcd_buf[i] = 0;
  232.             LCD1602_string(2,1,lcd_buf);
  233.             LCD1602_string(2,14,"   \0");
  234.             for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
  235.             lcd_buf[i] = 0;
  236.             LCD1602_string(2,14,lcd_buf);   
  237.         }
  238.         else if(flag_steep==2)
  239.         {
  240.             LCD1602_string(2,1,"                \0");
  241.             for(i=0;i<15;i++)lcd_buf[i] = timu_buf[timu_pos][i];
  242.             lcd_buf[i] = 0;
  243.             LCD1602_string(2,1,lcd_buf);        
  244.         }
  245.         while((PINB&0x02)==0);
  246.     }
  247.     else if((PINB&0x04)==0) //clr
  248.     {
  249.         if(flag_steep==1)
  250.         {   
  251.             for(i=0;i<2;i++)daan_buf[timu_pos][i]=' ';
  252.             input_cnt = 0;
  253.             LCD1602_string(2,14,"   \0");
  254.             while((PINB&0x04)==0);   
  255.         }
  256.     }
  257.     else if((PINB&0x08)==0) //OK
  258.     {
  259.         flag_steep = 2;
  260.         k = 5;
  261.         for(j=0;j<5;j++)
  262.         {
  263.             for(i=0;i<2;i++)
  264.             {
  265.                 if(timu_buf[j][i+13]!=daan_buf[j][i])
  266.                 {     
  267.                     k--;
  268.                     break;
  269.                 }
  270.             }
  271.         }
  272.         LCD1602_string(1,1,"                \0");
  273.         LCD1602_string(1,1," exam is over ! \0");
  274.         LCD1602_string(2,1,"                \0");
  275.         LCD1602_string(2,1,"currut :\0");
  276.         LCD1602_char(2,9,k+'0');
  277.         LCD1602_string(2,10," Err:\0");
  278.         LCD1602_char(2,16,5-k+'0');
  279.         USART_SEND(0x09);
  280.         USART_SEND(k);
  281.         while((PINB&0x08)==0);
  282.     }  
  283. }
  284. /***************KEY ***********************/
  285. #define KEY_H1 0
  286. #define KEY_H2 1
  287. #define KEY_H3 2
  288. #define KEY_H4 3

  289. #define KEY_L1 4
  290. #define KEY_L2 5
  291. #define KEY_L3 6
  292. #define KEY_L4 7

  293. #define KEY_H1_GPIO                PORTC
  294. #define KEY_H1_PIN                 PINC  
  295. #define KEY_H1_GPIO_DDR            DDRC
  296. #define KEY_H1_GPIO_DDR_OUT        (KEY_H1_GPIO_DDR |= BIT[KEY_H1])
  297. #define KEY_H1_GPIO_DDR_IN         (KEY_H1_GPIO_DDR &= ~BIT[KEY_H1])
  298. #define KEY_H1_SET()                        (KEY_H1_GPIO |= BIT[KEY_H1])
  299. #define KEY_H1_RST()               (KEY_H1_GPIO &= ~BIT[KEY_H1])
  300. #define KEY_H1_GET()               (KEY_H1_PIN&BIT[KEY_H1])

  301. #define KEY_H2_GPIO                PORTC
  302. #define KEY_H2_PIN                 PINC  
  303. #define KEY_H2_GPIO_DDR            DDRC
  304. #define KEY_H2_GPIO_DDR_OUT        (KEY_H2_GPIO_DDR |= BIT[KEY_H2])
  305. #define KEY_H2_GPIO_DDR_IN         (KEY_H2_GPIO_DDR &= ~BIT[KEY_H2])
  306. #define KEY_H2_SET()                        (KEY_H2_GPIO |= BIT[KEY_H2])
  307. #define KEY_H2_RST()               (KEY_H2_GPIO &= ~BIT[KEY_H2])
  308. #define KEY_H2_GET()               (KEY_H2_PIN&BIT[KEY_H2])

  309. #define KEY_H3_GPIO                PORTC
  310. #define KEY_H3_PIN                 PINC  
  311. #define KEY_H3_GPIO_DDR            DDRC
  312. #define KEY_H3_GPIO_DDR_OUT        (KEY_H3_GPIO_DDR |= BIT[KEY_H3])
  313. #define KEY_H3_GPIO_DDR_IN         (KEY_H3_GPIO_DDR &= ~BIT[KEY_H3])
  314. #define KEY_H3_SET()                        (KEY_H3_GPIO |= BIT[KEY_H3])
  315. #define KEY_H3_RST()               (KEY_H3_GPIO &= ~BIT[KEY_H3])
  316. #define KEY_H3_GET()               (KEY_H3_PIN&BIT[KEY_H3])

  317. #define KEY_H4_GPIO                PORTC
  318. #define KEY_H4_PIN                 PINC  
  319. #define KEY_H4_GPIO_DDR            DDRC
  320. #define KEY_H4_GPIO_DDR_OUT        (KEY_H4_GPIO_DDR |= BIT[KEY_H4])
  321. #define KEY_H4_GPIO_DDR_IN         (KEY_H4_GPIO_DDR &= ~BIT[KEY_H4])
  322. #define KEY_H4_SET()                        (KEY_H4_GPIO |= BIT[KEY_H4])
  323. #define KEY_H4_RST()               (KEY_H4_GPIO &= ~BIT[KEY_H4])
  324. #define KEY_H4_GET()               (KEY_H4_PIN&BIT[KEY_H4])

  325. #define KEY_L1_GPIO                PORTC
  326. #define KEY_L1_PIN                 PINC  
  327. #define KEY_L1_GPIO_DDR            DDRC
  328. #define KEY_L1_GPIO_DDR_OUT        (KEY_L1_GPIO_DDR |= BIT[KEY_L1])
  329. #define KEY_L1_GPIO_DDR_IN         (KEY_L1_GPIO_DDR &= ~BIT[KEY_L1])
  330. #define KEY_L1_SET()                        (KEY_L1_GPIO |= BIT[KEY_L1])
  331. #define KEY_L1_RST()               (KEY_L1_GPIO &= ~BIT[KEY_L1])
  332. #define KEY_L1_GET()               (KEY_L1_PIN&BIT[KEY_L1])

  333. #define KEY_L2_GPIO                PORTC
  334. #define KEY_L2_PIN                 PINC  
  335. #define KEY_L2_GPIO_DDR            DDRC
  336. #define KEY_L2_GPIO_DDR_OUT        (KEY_L2_GPIO_DDR |= BIT[KEY_L2])
  337. #define KEY_L2_GPIO_DDR_IN         (KEY_L2_GPIO_DDR &= ~BIT[KEY_L2])
  338. #define KEY_L2_SET()                        (KEY_L2_GPIO |= BIT[KEY_L2])
  339. #define KEY_L2_RST()               (KEY_L2_GPIO &= ~BIT[KEY_L2])
  340. #define KEY_L2_GET()               (KEY_L2_PIN&BIT[KEY_L2])

  341. #define KEY_L3_GPIO                PORTC
  342. #define KEY_L3_PIN                 PINC  
  343. #define KEY_L3_GPIO_DDR            DDRC
  344. #define KEY_L3_GPIO_DDR_OUT        (KEY_L3_GPIO_DDR |= BIT[KEY_L3])
  345. #define KEY_L3_GPIO_DDR_IN         (KEY_L3_GPIO_DDR &= ~BIT[KEY_L3])
  346. #define KEY_L3_SET()                        (KEY_L3_GPIO |= BIT[KEY_L3])
  347. #define KEY_L3_RST()               (KEY_L3_GPIO &= ~BIT[KEY_L3])
  348. #define KEY_L3_GET()               (KEY_L3_PIN&BIT[KEY_L3])

  349. #define KEY_L4_GPIO                PORTC
  350. #define KEY_L4_PIN                 PINC  
  351. #define KEY_L4_GPIO_DDR            DDRC
  352. #define KEY_L4_GPIO_DDR_OUT        (KEY_L4_GPIO_DDR |= BIT[KEY_L4])
  353. #define KEY_L4_GPIO_DDR_IN         (KEY_L4_GPIO_DDR &= ~BIT[KEY_L4])
  354. #define KEY_L4_SET()                        (KEY_L4_GPIO |= BIT[KEY_L4])
  355. #define KEY_L4_RST()               (KEY_L4_GPIO &= ~BIT[KEY_L4])
  356. #define KEY_L4_GET()               (KEY_L4_PIN&BIT[KEY_L4])

  357. unsigned int key_n[16];
  358. bit key_flag=0;
  359. void key_scan(void)
  360. {
  361.         key_flag=0;
  362.         /*****检测第1行****************/
  363.         KEY_H1_RST(); KEY_H2_SET();KEY_H3_SET();KEY_H4_SET();
  364.         if(KEY_L1_GET()==0)
  365.         {
  366.                 delay_ms(1);
  367.                 if(KEY_L1_GET()==0)
  368.                 {
  369.                         key_n[0]++;
  370.                         key_flag=1;        
  371.                 }
  372.         }
  373.         else if(KEY_L2_GET()==0)
  374.         {
  375.                 delay_ms(1);
  376.                 if(KEY_L2_GET()==0)
  377.                 {
  378.                         key_n[1]++;
  379.                         key_flag=1;        
  380.                 }
  381.         }
  382.         else if(KEY_L3_GET()==0)
  383.         {
  384.                 delay_ms(1);
  385.                 if(KEY_L3_GET()==0)
  386.                 {
  387.                         key_n[2]++;
  388.                         key_flag=1;        
  389.                 }
  390.         }
  391.         else if(KEY_L4_GET()==0)
  392.         {
  393.                 delay_ms(1);
  394.                 if(KEY_L4_GET()==0)
  395.                 {
  396.                         key_n[3]++;
  397.                         key_flag=1;        
  398.                 }
  399.         }

  400.         /*****检测第2行****************/
  401.         KEY_H1_SET(); KEY_H2_RST();KEY_H3_SET();KEY_H4_SET();
  402.         if(KEY_L1_GET()==0)
  403.         {
  404.                 delay_ms(1);
  405.                 if(KEY_L1_GET()==0)
  406.                 {
  407.                         key_n[4]++;
  408.                         key_flag=1;        
  409.                 }
  410.         }
  411.         else if(KEY_L2_GET()==0)
  412.         {
  413.                 delay_ms(1);
  414.                 if(KEY_L2_GET()==0)
  415.                 {
  416.                         key_n[5]++;
  417.                         key_flag=1;        
  418.                 }
  419.         }
  420.         else if(KEY_L3_GET()==0)
  421.         {
  422.                 delay_ms(1);
  423.                 if(KEY_L3_GET()==0)
  424.                 {
  425.                         key_n[6]++;
  426.                         key_flag=1;        
  427.                 }
  428.         }
  429.         else if(KEY_L4_GET()==0)
  430.         {
  431.                 delay_ms(1);
  432.                 if(KEY_L4_GET()==0)
  433.                 {
  434.                         key_n[7]++;
  435.                         key_flag=1;        
  436.                 }
  437.         }

  438.         /*****检测第3行****************/
  439.         KEY_H1_SET(); KEY_H2_SET();KEY_H3_RST();KEY_H4_SET();
  440.         if(KEY_L1_GET()==0)
  441.         {
  442.                 delay_ms(1);
  443.                 if(KEY_L1_GET()==0)
  444.                 {
  445.                         key_n[8]++;
  446.                         key_flag=1;        
  447.                 }
  448.         }
  449.         else if(KEY_L2_GET()==0)
  450.         {
  451.                 delay_ms(1);
  452.                 if(KEY_L2_GET()==0)
  453.                 {
  454.                         key_n[9]++;
  455.                         key_flag=1;        
  456.                 }
  457.         }
  458.         else if(KEY_L3_GET()==0)
  459.         {
  460.                 delay_ms(1);
  461.                 if(KEY_L3_GET()==0)
  462.                 {
  463.                         key_n[10]++;
  464.                         key_flag=1;        
  465.                 }
  466.         }
  467.         else if(KEY_L4_GET()==0)
  468.         {
  469.                 delay_ms(1);
  470.                 if(KEY_L4_GET()==0)
  471.                 {
  472.                         key_n[11]++;
  473.                         key_flag=1;        
  474.                 }
  475.         }

  476.         /*****检测第4行****************/
  477.         KEY_H1_SET(); KEY_H2_SET();KEY_H3_SET();KEY_H4_RST();
  478.         if(KEY_L1_GET()==0)
  479.         {
  480.                 delay_ms(1);
  481.                 if(KEY_L1_GET()==0)
  482.                 {
  483.                         key_n[12]++;
  484.                         key_flag=1;        
  485.                 }
  486.         }
  487.         else if(KEY_L2_GET()==0)
  488.         {
  489.                 delay_ms(1);
  490.                 if(KEY_L2_GET()==0)
  491.                 {
  492.                         key_n[13]++;
  493.                         key_flag=1;        
  494.                 }
  495.         }
  496.         else if(KEY_L3_GET()==0)
  497.         {
  498.                 delay_ms(1);
  499.                 if(KEY_L3_GET()==0)
  500.                 {
  501.                         key_n[14]++;
  502.                         key_flag=1;        
  503.                 }
  504.         }
  505.         else if(KEY_L4_GET()==0)
  506.         {
  507.                 delay_ms(1);
  508.                 if(KEY_L4_GET()==0)
  509.                 {
  510.                         key_n[15]++;
  511.                         key_flag=1;        
  512.                 }
  513.         }               
  514. }

  515. void key_pro()
  516. {
  517.         if(key_flag==0)
  518.         {
  519.                 if(key_n[0]>0)//0
  520.                 {
  521.                         key_n[0]=0;        
  522.                         input_dat(0);
  523.                 }
  524.                 else if(key_n[1]>0)//1
  525.                 {
  526.                         key_n[1]=0;
  527.                         input_dat(1);        
  528.                 }
  529.                 else if(key_n[2]>0)//2
  530.                 {
  531.                         key_n[2]=0;
  532.                         input_dat(2);        
  533.                 }
  534.                 else if(key_n[3]>0)//3
  535.                 {
  536.                         key_n[3]=0;
  537.             input_dat(3);        
  538.                 }
  539.                 else if(key_n[4]>0)//4
  540.                 {
  541.                         key_n[4]=0;        
  542.                         input_dat(4);
  543.                 }
  544.                 else if(key_n[5]>0)//5
  545.                 {
  546.                         key_n[5]=0;        
  547.                         input_dat(5);
  548.                 }
  549.                 else if(key_n[6]>0)//6
  550.                 {
  551.                         key_n[6]=0;        
  552.                         input_dat(6);
  553.                 }
  554.                 else if(key_n[7]>0)//乘位
  555.                 {
  556.                         key_n[7]=0;
  557.             input_dat(7);        
  558.                 }
  559.                 else if(key_n[8]>0)//1
  560.                 {
  561.                         key_n[8]=0;        
  562.                         input_dat(8);
  563.                 }
  564.                 else if(key_n[9]>0)//2
  565.                 {
  566.                         key_n[9]=0;        
  567.                         input_dat(9);
  568.                 }
  569.                 else if(key_n[10]>0)//3
  570.                 {
  571.                         key_n[10]=0;
  572.                         input_dat('A');        
  573.                 }
  574.                 else if(key_n[11]>0)//方式数字转换
  575.                 {
  576.                         key_n[11]=0;
  577.             input_dat('B');        
  578.                 }
  579.                 else if(key_n[12]>0)//明暗转换
  580.                 {
  581.                         key_n[12]=0;
  582.             input_dat('C');        
  583.                 }
  584.                 else if(key_n[13]>0)//0
  585.                 {
  586.                         key_n[13]=0;
  587.                         input_dat('D');        
  588.                 }
  589.                 else if(key_n[14]>0)//接收
  590.                 {
  591.                         key_n[14]=0;
  592.             input_dat('E');
  593.                 }
  594.                 else if(key_n[15]>0)//发送
  595.                 {
  596.                         key_n[15]=0;
  597.             input_dat('F');        
  598.                 }                        
  599.         }
  600. }
  601. void key(void)
  602. {
  603.         key_scan();
  604.         key_pro();
  605. }
  606. /**************UART*************************/
  607. void USART_INIT(void)
  608. {
  609.     PORTD = 0x02; // TXD(PD1)输出
  610.     DDRD  = 0x00; // RXD(PD0)输入,上拉有效
  611.     UCSRA = 0x00; // USART初始化
  612.     UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // 允许RXC中断,接收允许,发送允许
  613.     // UCSRB = 0x98;
  614.     UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
  615.     // UCSRC = 0x86;
  616.     UBRRH = BAUD_H; // 设置波特率,1200bps
  617.     UBRRL = BAUD_L;
  618. }
  619. void USART_SEND(unsigned char data) // USART发送子程序
  620. {
  621.     while (!(UCSRA & (1<<UDRE))); // 等待发送寄存器空
  622.     UDR = data; // 发送数据
  623. }
  624. /**************LCD*************************/
  625. #define LCD_DATA_GPIO             PORTA//LCD数据接口定义
  626. #define LCD_DATA_GPIO_DDR         DDRA
  627. #define SET_LCD_DATA_GPIO_DDR     (LCD_DATA_GPIO_DDR|=0XFF)
  628. #define CLR_LCD_DATA_GPIO_DDR     (LCD_DATA_GPIO_DDR&=0X00)

  629. #define LCD_RS 5
  630. #define LCD_RW 6
  631. #define LCD_EN 7

  632. #define LCD_RS_GPIO                PORTB
  633. #define LCD_RS_GPIO_DDR            DDRB
  634. #define SET_LCD_RS_GPIO_DDR        (LCD_RS_GPIO_DDR|=BIT[LCD_RS])
  635. #define CLR_LCD_RS_GPIO_DDR        (LCD_RS_GPIO_DDR&=~BIT[LCD_RS])
  636. #define RS_SET() (LCD_RS_GPIO|=BIT[LCD_RS])
  637. #define RS_RST() (LCD_RS_GPIO&=~BIT[LCD_RS])

  638. #define LCD_RW_GPIO                PORTB
  639. #define LCD_RW_GPIO_DDR            DDRB
  640. #define SET_LCD_RW_GPIO_DDR        (LCD_RW_GPIO_DDR|=BIT[LCD_RW])
  641. #define CLR_LCD_RW_GPIO_DDR        (LCD_RW_GPIO_DDR&=~BIT[LCD_RW])
  642. #define RW_SET() (LCD_RW_GPIO|=BIT[LCD_RW])
  643. #define RW_RST() (LCD_RW_GPIO&=~BIT[LCD_RW])   

  644. #define LCD_EN_GPIO                PORTB
  645. #define LCD_EN_GPIO_DDR            DDRB
  646. #define SET_LCD_EN_GPIO_DDR        (LCD_EN_GPIO_DDR|=BIT[LCD_EN])
  647. #define CLR_LCD_EN_GPIO_DDR        (LCD_EN_GPIO_DDR&=~BIT[LCD_EN])
  648. #define EN_SET() (LCD_EN_GPIO|=BIT[LCD_EN])
  649. #define EN_RST() (LCD_EN_GPIO&=~BIT[LCD_EN])



  650. void lcd_gpio_init(void)
  651. {
  652.     SET_LCD_RS_GPIO_DDR;
  653.     SET_LCD_RW_GPIO_DDR;
  654.     SET_LCD_EN_GPIO_DDR;
  655. }
  656. /*****************************************************
  657. 函数功能:将模式设置指令或显示地址写入液晶模块
  658. 入口参数:dictate
  659. ***************************************************/
  660. void WriteInstruction (unsigned char dictate)
  661. {   
  662.      delay_ms(2);
  663.      RS_RST();                  //根据规定,RS和R/W同时为低电平时,可以写入指令
  664.      RW_RST();   
  665.      EN_RST();                   //E置低电平(根据表8-6,写指令时,E为高脉冲,
  666.                              // 就是让E从0到1发生正跳变,所以应先置"0"
  667.      delay_us(2);            //空操作两个机器周期,给硬件反应时间
  668.      LCD_DATA_GPIO=dictate;            //将数据送入P0口,即写入指令或地址
  669.      delay_us(4);               //空操作四个机器周期,给硬件反应时间
  670.      EN_SET();                   //E置高电平
  671.      delay_us(4);               //空操作四个机器周期,给硬件反应时间
  672.      EN_RST();                  //当E由高电平跳变成低电平时,液晶模块开始执行命令
  673. }
  674. /*****************************************************
  675. 函数功能:指定字符显示的实际地址
  676. 入口参数:x
  677. ***************************************************/
  678. void WriteAddress(unsigned char x)
  679. {
  680.      WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
  681. }
  682. /*****************************************************
  683. 函数功能:将数据(字符的标准ASCII码)写入液晶模块
  684. 入口参数:y(为字符常量)
  685. ***************************************************/
  686. void WriteData(unsigned char y)
  687. {
  688.       delay_ms(2);  
  689.       RS_SET();           //RS为高电平,RW为低电平时,可以写入数据
  690.       RW_RST();
  691.       EN_RST();            //E置低电平(根据表8-6,写指令时,E为高脉冲,
  692.                        // 就是让E从0到1发生正跳变,所以应先置"0"
  693.       LCD_DATA_GPIO=y;           //将数据送入P0口,即将数据写入液晶模块
  694.       delay_us(4);      //空操作四个机器周期,给硬件反应时间
  695.       EN_SET();          //E置高电平
  696.       delay_us(40);       //空操作四个机器周期,给硬件反应时间
  697.           EN_RST();            //当E由高电平跳变成低电平时,液晶模块开始执行命令
  698. }

  699. void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//显示一个字节
  700. {
  701.         unsigned char a;
  702.         if(hang == 1)a = 0x00;
  703.         if(hang == 2)a = 0x40;
  704.         a = a + lie - 1;
  705.         WriteAddress(a);//向LCD写入数据要显示的地址
  706.         WriteData(sign);//向LCD写入要显示的数据
  707. }
  708. void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD写入要显示的字符串
  709. {
  710.         unsigned char a;
  711.         if(hang == 1) a = 0x00;
  712.         if(hang == 2) a = 0x40;
  713.         a = a + lie - 1;
  714.         WriteAddress(a);//写入显示的首地址
  715.         while(1)
  716.         {
  717.                 if(*p == '\0') break;
  718.                 WriteData(*p);
  719.                 p++;
  720.         }
  721. }
  722. /*****************************************************
  723. 函数功能:对LCD的显示模式进行初始化设置
  724. ***************************************************/
  725. void LcdInitiate(void)
  726. {
  727.     delay_ms(15);             //延时15ms,首次写指令时应给LCD一段较长的反应时间
  728.     WriteInstruction(0x38);  //显示模式设置:16×2显示,5×7点阵,8位数据接口
  729.     delay_ms(5);   //延时5ms 
  730.     WriteInstruction(0x38);
  731.     delay_ms(5);
  732.     WriteInstruction(0x38);
  733.     delay_ms(5);
  734.     WriteInstruction(0x0c);  //显示模式设置:显示开,有光标,光标闪烁
  735.     delay_ms(5);
  736.     WriteInstruction(0x06);  //显示模式设置:光标右移,字符不移
  737.     delay_ms(5);
  738.     WriteInstruction(0x01);  //清屏幕指令,将以前的显示内容清除
  739.     delay_ms(5);
  740.     LCD1602_string(1,1," \0");
  741. }
  742. 终端程序
  743. #include <mega16.h>
  744. #include <delay.h>

  745. #define BAUD    9600    // 波特率采用9600bps
  746. #define CRYSTAL 4000000 // 系统时钟4MHz

  747. //计算和定义波特率设置参数
  748. #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率计算
  749. #define BAUD_H (unsigned char)(BAUD_SETTING>>8) // 高8位
  750. #define BAUD_L (unsigned char)(BAUD_SETTING) // 低8位

  751. unsigned char const num_str[]={"0123456789"};
  752. void USART_INIT(void);
  753. void USART_SEND(unsigned char data); // USART发送子程序
  754. void USART_SEND_N(unsigned char num,unsigned char *buf);
  755. interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中断服务
  756. void lcd_gpio_init(void);
  757. void LcdInitiate(void);
  758. void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p);
  759. void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign);
  760. unsigned char rx_buf[16],rx_cnt=0,rx_cnt_r=0;
  761. void main(void)
  762. {
  763.     unsigned char dat=0,i,flag_start = 0,lcd_buf[16],lcd_cnt;
  764.     unsigned int tim_cnt = 0,t = 0;
  765.     USART_INIT();
  766.     lcd_gpio_init();
  767.     LcdInitiate();
  768.     LCD1602_string(1,1,"Name:CDE\0");
  769.     LCD1602_string(2,1,"Num:987654\0");
  770.     #asm("sei") // 开中断      
  771.     while(1)
  772.     {     
  773.         delay_ms(1);
  774.         if(flag_start==2)
  775.         {
  776.             
  777.         }
  778.         else if(flag_start==1)
  779.         {
  780.                
  781.         }
  782.         if(rx_cnt)
  783.         {
  784.             if(rx_cnt == rx_cnt_r)
  785.             {   
  786.                 if(rx_buf[0]==0x09&&rx_cnt==2)
  787.                 {
  788.                     LCD1602_string(1,1,"                \0");
  789.                     LCD1602_string(1,1," exam is over ! \0");
  790.                     LCD1602_string(2,1,"                \0");
  791.                     LCD1602_string(2,1,"currut :\0");
  792.                     LCD1602_char(2,9,rx_buf[1]+'0');
  793.                     LCD1602_string(2,10," Err:\0");
  794.                     LCD1602_char(2,16,5-rx_buf[1]+'0');     
  795.                 }
  796.                 else if(rx_buf[0]==0x00&&rx_cnt==10)
  797.                 {
  798.                     lcd_cnt = 0;
  799.                     for(i=0;i<3;i++)
  800.                     {
  801.                         if(rx_buf[i+1]!=('C'+i))break;   
  802.                     }
  803.                     if(i==3)
  804.                     {
  805.                         for(i=0;i<6;i++)
  806.                         {
  807.                             if(rx_buf[i+4]!=(9-i))break;   
  808.                         }   
  809.                     }
  810.                     if(i==6)
  811.                     {
  812.                         flag_start = 1;      
  813.                         LCD1602_string(1,1,"From the end of \0");
  814.                         LCD1602_string(2,1,"the exam->00:00 \0");
  815.                         //发送时间
  816.                         lcd_cnt = 0;
  817.                         lcd_buf[lcd_cnt++] = 0x01;//发送时间
  818.                         lcd_buf[lcd_cnt++] = 0x02;//发送分钟
  819.                         lcd_buf[lcd_cnt++] = 0x00;//发送秒钟
  820.                         for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);
  821.                        delay_ms(300);
  822.                         USART_SEND(0x02); //发送题1
  823.                         USART_SEND_N(15,"3+1*3+6/2=   9 ");
  824.                         delay_ms(300);
  825.                         USART_SEND(0x03); //发送题2
  826.                         USART_SEND_N(15,"5+10/5+1*1=  11");
  827.                         delay_ms(300);
  828.                         USART_SEND(0x04); //发送题3
  829.                         USART_SEND_N(15,"9-3*3+2*1=   2 ");
  830.                         delay_ms(300);
  831.                         USART_SEND(0x05); //发送题4
  832.                         USART_SEND_N(15,"12/3+8/4+2=  8 ");
  833.                         delay_ms(300);
  834.                         USART_SEND(0x06); //发送题5
  835.                         USART_SEND_N(15,"15/3+2*6-11= 6 ");
  836.                     }
  837.                     else
  838.                     {
  839.                         lcd_cnt = 0;
  840.                         lcd_buf[lcd_cnt++] = 0x00;//发送考生校验
  841.                         lcd_buf[lcd_cnt++] = 0x01;//发送错误
  842.                         for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);   
  843.                     }      
  844.                 }
  845.                 else if(rx_buf[0]==0x01&&rx_cnt==3)//收到开始考试指令
  846.                 {
  847.                         tim_cnt =  rx_buf[1];
  848.                         tim_cnt =  tim_cnt*60 + rx_buf[2];
  849.                         lcd_cnt = 0;
  850.                         lcd_buf[lcd_cnt++] = rx_buf[1]/10%10+'0';
  851.                         lcd_buf[lcd_cnt++] = rx_buf[1]%10+'0';
  852.                         lcd_buf[lcd_cnt++] = 0;
  853.                         LCD1602_string(2,11,lcd_buf);
  854.                         lcd_cnt = 0;
  855.                         lcd_buf[lcd_cnt++] = rx_buf[2]/10%10+'0';
  856.                         lcd_buf[lcd_cnt++] = rx_buf[2]%10+'0';
  857.                         lcd_buf[lcd_cnt++] = 0;
  858.                         LCD1602_string(2,14,lcd_buf);
  859.                         
  860.                 }
  861.                 rx_cnt = 0;
  862.             }
  863.             rx_cnt_r = rx_cnt;
  864.         }
  865.     }
  866. }


  867. interrupt [USART_RXC] void USART_RCV_INT(void) // USART接收中断服务
  868. {
  869.     unsigned char data;
  870.     data = UDR; // 接收数据
  871.     if(rx_cnt<16)
  872.     {
  873.         rx_buf[rx_cnt++] = data;
  874.     }
  875. }

  876. /**************UART*************************/
  877. void USART_INIT(void)
  878. {
  879.     PORTD = 0x02; // TXD(PD1)输出
  880.     DDRD  = 0x00; // RXD(PD0)输入,上拉有效
  881.     UCSRA = 0x00; // USART初始化
  882.     UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // 允许RXC中断,接收允许,发送允许
  883.     // UCSRB = 0x98;
  884.     UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
  885.     // UCSRC = 0x86;
  886.     UBRRH = BAUD_H; // 设置波特率,1200bps
  887.     UBRRL = BAUD_L;
  888. }
  889. void USART_SEND(unsigned char data) // USART发送子程序
  890. {
  891.     while (!(UCSRA & (1<<UDRE))); // 等待发送寄存器空
  892.     UDR = data; // 发送数据
  893. }
  894. void USART_SEND_N(unsigned char num,unsigned char *buf)
  895. {
  896.     unsigned char i;
  897.     for(i=0;i<num;i++)
  898.     {
  899.         USART_SEND(buf[i]);   
  900.     }   
  901. }
  902. /**************LCD*************************/
  903. #define BIT0 0X01
  904. #define BIT1 0X02
  905. #define BIT2 0X04
  906. #define BIT3 0X08
  907. #define BIT4 0X10
  908. #define BIT5 0X20
  909. #define BIT6 0X40
  910. #define BIT7 0X80

  911. unsigned char const BIT[]={BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7};

  912. #define LCD_DATA_GPIO             PORTA//LCD数据接口定义
  913. #define LCD_DATA_GPIO_DDR         DDRA
  914. #define SET_LCD_DATA_GPIO_DDR     (LCD_DATA_GPIO_DDR|=0XFF)
  915. #define CLR_LCD_DATA_GPIO_DDR     (LCD_DATA_GPIO_DDR&=0X00)

  916. #define LCD_RS 5
  917. #define LCD_RW 6
  918. #define LCD_EN 7

  919. #define LCD_RS_GPIO                PORTB
  920. #define LCD_RS_GPIO_DDR            DDRB
  921. #define SET_LCD_RS_GPIO_DDR        (LCD_RS_GPIO_DDR|=BIT[LCD_RS])
  922. #define CLR_LCD_RS_GPIO_DDR        (LCD_RS_GPIO_DDR&=~BIT[LCD_RS])
  923. #define RS_SET() (LCD_RS_GPIO|=BIT[LCD_RS])
  924. #define RS_RST() (LCD_RS_GPIO&=~BIT[LCD_RS])

  925. #define LCD_RW_GPIO                PORTB
  926. #define LCD_RW_GPIO_DDR            DDRB
  927. #define SET_LCD_RW_GPIO_DDR        (LCD_RW_GPIO_DDR|=BIT[LCD_RW])
  928. #define CLR_LCD_RW_GPIO_DDR        (LCD_RW_GPIO_DDR&=~BIT[LCD_RW])
  929. #define RW_SET() (LCD_RW_GPIO|=BIT[LCD_RW])
  930. #define RW_RST() (LCD_RW_GPIO&=~BIT[LCD_RW])   

  931. #define LCD_EN_GPIO                PORTB
  932. #define LCD_EN_GPIO_DDR            DDRB
  933. #define SET_LCD_EN_GPIO_DDR        (LCD_EN_GPIO_DDR|=BIT[LCD_EN])
  934. #define CLR_LCD_EN_GPIO_DDR        (LCD_EN_GPIO_DDR&=~BIT[LCD_EN])
  935. #define EN_SET() (LCD_EN_GPIO|=BIT[LCD_EN])
  936. #define EN_RST() (LCD_EN_GPIO&=~BIT[LCD_EN])



  937. void lcd_gpio_init(void)
  938. {
  939.     SET_LCD_RS_GPIO_DDR;
  940.     SET_LCD_RW_GPIO_DDR;
  941.     SET_LCD_EN_GPIO_DDR;
  942. }
  943. /*****************************************************
  944. 函数功能:将模式设置指令或显示地址写入液晶模块
  945. 入口参数:dictate
  946. ***************************************************/
  947. void WriteInstruction (unsigned char dictate)
  948. {   
  949.      delay_ms(2);
  950.      RS_RST();                  //根据规定,RS和R/W同时为低电平时,可以写入指令
  951.      RW_RST();   
  952.      EN_RST();                   //E置低电平(根据表8-6,写指令时,E为高脉冲,
  953.                              // 就是让E从0到1发生正跳变,所以应先置"0"
  954.      delay_us(2);            //空操作两个机器周期,给硬件反应时间
  955.      LCD_DATA_GPIO=dictate;            //将数据送入P0口,即写入指令或地址
  956.      delay_us(4);               //空操作四个机器周期,给硬件反应时间
  957.      EN_SET();                   //E置高电平
  958.      delay_us(4);               //空操作四个机器周期,给硬件反应时间
  959.      EN_RST();                  //当E由高电平跳变成低电平时,液晶模块开始执行命令
  960. }
  961. /*****************************************************
  962. 函数功能:指定字符显示的实际地址
  963. 入口参数:x
  964. ***************************************************/
  965. void WriteAddress(unsigned char x)
  966. {
  967.      WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
  968. }
  969. /*****************************************************
  970. 函数功能:将数据(字符的标准ASCII码)写入液晶模块
  971. 入口参数:y(为字符常量)
  972. ***************************************************/
  973. void WriteData(unsigned char y)
  974. {
  975.       delay_ms(2);  
  976.       RS_SET();           //RS为高电平,RW为低电平时,可以写入数据
  977.       RW_RST();
  978.       EN_RST();            //E置低电平(根据表8-6,写指令时,E为高脉冲,
  979.                        // 就是让E从0到1发生正跳变,所以应先置"0"
  980.       LCD_DATA_GPIO=y;           //将数据送入P0口,即将数据写入液晶模块
  981.       delay_us(4);      //空操作四个机器周期,给硬件反应时间
  982.       EN_SET();          //E置高电平
  983.       delay_us(40);       //空操作四个机器周期,给硬件反应时间
  984.           EN_RST();            //当E由高电平跳变成低电平时,液晶模块开始执行命令
  985. }

  986. void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//显示一个字节
  987. {
  988.         unsigned char a;
  989.         if(hang == 1)a = 0x00;
  990.         if(hang == 2)a = 0x40;
  991.         a = a + lie - 1;
  992.         WriteAddress(a);//向LCD写入数据要显示的地址
  993.         WriteData(sign);//向LCD写入要显示的数据
  994. }
  995. void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD写入要显示的字符串
  996. {
  997.         unsigned char a;
  998.         if(hang == 1) a = 0x00;
  999.         if(hang == 2) a = 0x40;
  1000.         a = a + lie - 1;
  1001.         WriteAddress(a);//写入显示的首地址
  1002.         while(1)
  1003.         {
  1004.                 if(*p == '\0') break;
  1005.                 WriteData(*p);
  1006.                 p++;
  1007.         }
  1008. }
  1009. /*****************************************************
  1010. 函数功能:对LCD的显示模式进行初始化设置
  1011. ***************************************************/
  1012. void LcdInitiate(void)
  1013. {
  1014.     delay_ms(15);             //延时15ms,首次写指令时应给LCD一段较长的反应时间
  1015.     WriteInstruction(0x38);  //显示模式设置:16×2显示,5×7点阵,8位数据接口
  1016.     delay_ms(5);   //延时5ms 
  1017.     WriteInstruction(0x38);
  1018.     delay_ms(5);
  1019.     WriteInstruction(0x38);
  1020.     delay_ms(5);
  1021.     WriteInstruction(0x0c);  //显示模式设置:显示开,有光标,光标闪烁
  1022.     delay_ms(5);
  1023.     WriteInstruction(0x06);  //显示模式设置:光标右移,字符不移
  1024.     delay_ms(5);
  1025.     WriteInstruction(0x01);  //清屏幕指令,将以前的显示内容清除
  1026.     delay_ms(5);
  1027.     LCD1602_string(1,1," \0");
  1028. }
复制代码

全部资料51hei下载地址:
atmega16设计电子考试系统仿真及程序.rar (870.03 KB, 下载次数: 32)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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