- 功能用途:采用两个单片机系统实现四则运算考试及判卷功能,具体内容包括:
⑴两个单片机系统分别作为服务器和答题终端。服务器负责验证考生个人信息,发送试题到终端,定时收卷及判分功能。答题终端负责输入考生个人信息,答题,修改答案及传送答案到服务器。 ⑵服务器验证考生个人信息,若信息不正确则向终端发出提示信息。信息验证正确后将试题发送到答题终端,同时开始计时。无论答题是否完成,考试时间到则强制收题。也可在考试时间尚有剩余时接收答题终端发送过来的答案。收题后进行判分工作并给出最终得分及答题情况统计信息。对回答错误的题目则给出原题及正确答案。 ⑶答题终端在收到试题后向考生显示试题内容(可逐道显示)并接受考生输入的答案。试题显示应具备翻页功能以允许考生反复浏览试题或检查所作答案。当考生检查完毕且考试时间尚有剩余,允许考生向服务器发送最终答案。 ⑷实现服务器和答题终端的两个单片机系统均应包含键盘和LCD液晶显示模块。两个单片机系统通过串口进行通信。 机系统通过串口进行通信。 ⑴给出使用说明,包括按键的定义,操作方法等。 ⑵所有功能用途均可实现且各功能转换正常(模拟5道题即可)。 ⑶考生个人信息包括考生姓名(可用拼音表示)和6位的学号。 ⑷验收时需要演示考生个人信息不正确时的处理情况; ⑸服务器和终端都应实时显示考试剩余时间; ⑹四则运算应覆盖加减乘除四种运算; ⑺终端答题时,在未提交答案前应允许反复浏览或修改答案
终端的atmega16单片机电路连接如图所示。复位端口连一个上拉电阻,下接一个按键,按键按下时,终端单片机复位,能使终端的显示屏回到初始的界面。在引脚XTAL1和XTAL2上外接石英晶体和电容组成的谐振回路,配合片内的OSC振荡电路构成振荡源。 终端的显示屏设计如图所示,里面有预置的姓名和学号,只有当服务器输入的和终端预置的一致时才能进入系统。 终端的初始页面 通过验证进入系统后终端会开始计时并 答题结束之后,终端会显示正确和错误的题目个数 显示剩余时间,如果验证失败则保持初 在时间规定内,考生可自己提交答案。超出时间的 始页面不变。 话,则系统强制收卷 客户端单片机与终端单片机有相似的地方的这里不做赘述。 客户端键盘展示 键盘完成输入姓名学号、答题功能。旁边还有四个按键,可以实现在答题的时候,上下翻查看题目,答题有误的情况下清除原有答案,和作答完毕时提交答案的功能。 客户端功能展示 初始页面如图所示,要求输入姓名学号,输入有误则会显示“有一个错误,请重新输入” 输入正确则会进入考试系统 显示考试开始,计时并显示剩余的时间。这里我们准备了5道题目,按上下键可以翻动题目清除可以清除答案 考试结束服务端会显示正确和错误的题目个数。 此时按上下键可以查看所有题目和答案 。
单片机源程序如下:
用户端
- #include <mega16.h>
- #include <delay.h>
- #define BAUD 9600 // 波特率采用9600bps
- #define CRYSTAL 4000000 // 系统时钟8MHz
- #define BIT0 0X01
- #define BIT1 0X02
- #define BIT2 0X04
- #define BIT3 0X08
- #define BIT4 0X10
- #define BIT5 0X20
- #define BIT6 0X40
- #define BIT7 0X80
- unsigned char const BIT[]={BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7};
- //计算和定义波特率设置参数
- #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率计算
- #define BAUD_H (unsigned char)(BAUD_SETTING>>8) // 高8位
- #define BAUD_L (unsigned char)(BAUD_SETTING) // 低8位
- unsigned char const num_str[]={"0123456789"};
- void USART_INIT(void);
- void USART_SEND(unsigned char data); // USART发送子程序
- interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中断服务
- void lcd_gpio_init(void);
- void LcdInitiate(void);
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p);
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign);
- void KEY_INIT(void);
- void KEY_CHECK(void);
- void key(void);
- unsigned char input_buf[16],input_cnt = 0;
- unsigned char timu_buf[5][16],daan_buf[5][2];
- unsigned char flag_steep = 0,rx_buf[16],rx_cnt=0,rx_cnt_r=0;
- unsigned char timu_pos = 0;
- unsigned char lcd_buf[16],lcd_cnt=0;
- void main( void )
- {
- unsigned char dat=0,i,lcd_buf[16],lcd_cnt;
- unsigned int tim_cnt = 0,t = 0;
- KEY_INIT();
- USART_INIT();
- lcd_gpio_init();
- LcdInitiate();
- LCD1602_string(1,1,"Your Name:");
- LCD1602_string(2,1,"Your Num:");
- #asm("sei") // 开中断
- flag_steep = 0;
- while(1)
- {
- delay_ms(1);
- key();
- KEY_CHECK();
- if(flag_steep==0)//输入考生信息
- {
- if(input_cnt<=3)
- {
- lcd_cnt = 0;
- for(i=0;i<input_cnt;i++)
- {
- lcd_buf[lcd_cnt++] = input_buf[i];
- }
- lcd_buf[lcd_cnt++] = 0;
- //LCD1602_string(1,11," \0");
- LCD1602_string(1,11,lcd_buf);
- }
- else if(input_cnt>3&&input_cnt<=9)
- {
- lcd_cnt = 0;
- for(i=0;i<(input_cnt-3);i++)
- {
- lcd_buf[lcd_cnt++] = input_buf[i+3]+'0';
- }
- lcd_buf[lcd_cnt++] = 0;
- LCD1602_string(2,10,lcd_buf);
- if(input_cnt==9)
- {
- input_cnt = 0;
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x00;//发送考生信息
- for(i=0;i<9;i++)lcd_buf[lcd_cnt++] = input_buf[i];
- for(i=0;i<10;i++)USART_SEND(lcd_buf[i]);
- }
- }
- }
- else if(flag_steep==1)
- {
- if(t<1000)t++;
- else
- {
- t= 0;
- tim_cnt--;
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x01;//发送剩余时间
- lcd_buf[lcd_cnt++] = tim_cnt/60;//发送剩余分钟
- lcd_buf[lcd_cnt++] = tim_cnt%60;//发送剩余秒钟
- for(i=0;i<3;i++)USART_SEND(lcd_buf[i]);
- LCD1602_string(1,1,"Time left:");
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = tim_cnt/60/10%10+'0';
- lcd_buf[lcd_cnt++] = tim_cnt/60%10+'0';
- lcd_buf[lcd_cnt++] = ':';
- lcd_buf[lcd_cnt++] = tim_cnt%60/10%10+'0';
- lcd_buf[lcd_cnt++] = tim_cnt%60%10+'0';
- lcd_buf[lcd_cnt++] = 0;
- LCD1602_string(1,11,lcd_buf);
- if(tim_cnt==0)
- {
- flag_steep = 2;
- LCD1602_string(2,1,"The exam is over\0");
- }
- }
- }
- if(rx_cnt)
- {
- if(rx_cnt == rx_cnt_r)
- {
- if(rx_cnt==16)
- {
- for(i=0;i<15;i++)
- {
- timu_buf[rx_buf[0]-2][i] = rx_buf[i+1];
- }
- LCD1602_string(2,1," \0");
- for(i=0;i<13;i++)lcd_buf[i] = timu_buf[0][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,1,lcd_buf);
- }
- else if(rx_buf[0]==0x00&&rx_buf[1]==0x01&&rx_cnt==2)
- {
- LCD1602_string(1,1," \0");
- LCD1602_string(2,1," \0");
- LCD1602_string(1,1,"There is an Err!\0");
- LCD1602_string(2,1,"Please Again ! \0");
- delay_ms(1000);
- LCD1602_string(1,1," \0");
- LCD1602_string(2,1," \0");
- LCD1602_string(1,1,"Your Name:");
- LCD1602_string(2,1,"Your Num:");
- input_cnt = 0;
- }
- else if(rx_buf[0]==0x01&&rx_cnt==3)//收到开始考试指令
- {
- tim_cnt = rx_buf[1];
- tim_cnt = tim_cnt*60 + rx_buf[2];
- flag_steep = 1;
- t = 0;
- LCD1602_string(1,1," lets start \0");
- LCD1602_string(2,1," the exam \0");
- }
- rx_cnt = 0;
- }
- rx_cnt_r = rx_cnt;
- }
- }
- }
- void input_dat(unsigned char dat)
- {
- unsigned char i;
- if(flag_steep==0&&input_cnt<3&&(dat>='A'&&dat<='F'))
- {
- input_buf[input_cnt++] = dat;
- }
- else if(flag_steep==0&&input_cnt>=3&&input_cnt<9&&(dat>=0&&dat<=9))
- {
- input_buf[input_cnt++] = dat;
- }
- else if(flag_steep==1&&input_cnt<2&&(dat>=0&&dat<=9))
- {
- if(input_cnt==0)
- {
- for(i=0;i<2;i++)daan_buf[timu_pos][i]=' ';
- }
- daan_buf[timu_pos][input_cnt++] = dat+'0';
- if(input_cnt==2)input_cnt = 0;
- LCD1602_string(2,14," \0");
- for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,14,lcd_buf);
- }
- }
- interrupt [USART_RXC] void USART_RCV_INT(void) // USART接收中断服务
- {
- unsigned char data;
- data = UDR; // 接收数据
- if(rx_cnt<16)
- {
- rx_buf[rx_cnt++] = data;
- }
- }
- /**************KEY*************************/
- void KEY_INIT(void)
- {
- PORTC = 0xF0; //输出
- DDRC = 0x0F; //输入,上拉有效
- PORTB |= 0x0F;
- DDRB &= 0xF0;
- }
- void KEY_CHECK(void)
- {
- unsigned char i,j,k;
- if((PINB&0x01)==0) //+
- {
- if(timu_pos<4)timu_pos++;
- else timu_pos = 0;
- if(flag_steep==1)
- {
- LCD1602_string(2,1," \0");
- for(i=0;i<13;i++)lcd_buf[i] = timu_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,1,lcd_buf);
- LCD1602_string(2,14," \0");
- for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,14,lcd_buf);
- }
- else if(flag_steep==2)
- {
- LCD1602_string(2,1," \0");
- for(i=0;i<15;i++)lcd_buf[i] = timu_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,1,lcd_buf);
- }
- while((PINB&0x01)==0);
- }
- else if((PINB&0x02)==0) //-
- {
- if(timu_pos>0)timu_pos--;
- else timu_pos = 4;
- if(flag_steep==1)
- {
- LCD1602_string(2,1," \0");
- for(i=0;i<13;i++)lcd_buf[i] = timu_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,1,lcd_buf);
- LCD1602_string(2,14," \0");
- for(i=0;i<2;i++)lcd_buf[i] = daan_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,14,lcd_buf);
- }
- else if(flag_steep==2)
- {
- LCD1602_string(2,1," \0");
- for(i=0;i<15;i++)lcd_buf[i] = timu_buf[timu_pos][i];
- lcd_buf[i] = 0;
- LCD1602_string(2,1,lcd_buf);
- }
- while((PINB&0x02)==0);
- }
- else if((PINB&0x04)==0) //clr
- {
- if(flag_steep==1)
- {
- for(i=0;i<2;i++)daan_buf[timu_pos][i]=' ';
- input_cnt = 0;
- LCD1602_string(2,14," \0");
- while((PINB&0x04)==0);
- }
- }
- else if((PINB&0x08)==0) //OK
- {
- flag_steep = 2;
- k = 5;
- for(j=0;j<5;j++)
- {
- for(i=0;i<2;i++)
- {
- if(timu_buf[j][i+13]!=daan_buf[j][i])
- {
- k--;
- break;
- }
- }
- }
- LCD1602_string(1,1," \0");
- LCD1602_string(1,1," exam is over ! \0");
- LCD1602_string(2,1," \0");
- LCD1602_string(2,1,"currut :\0");
- LCD1602_char(2,9,k+'0');
- LCD1602_string(2,10," Err:\0");
- LCD1602_char(2,16,5-k+'0');
- USART_SEND(0x09);
- USART_SEND(k);
- while((PINB&0x08)==0);
- }
- }
- /***************KEY ***********************/
- #define KEY_H1 0
- #define KEY_H2 1
- #define KEY_H3 2
- #define KEY_H4 3
- #define KEY_L1 4
- #define KEY_L2 5
- #define KEY_L3 6
- #define KEY_L4 7
- #define KEY_H1_GPIO PORTC
- #define KEY_H1_PIN PINC
- #define KEY_H1_GPIO_DDR DDRC
- #define KEY_H1_GPIO_DDR_OUT (KEY_H1_GPIO_DDR |= BIT[KEY_H1])
- #define KEY_H1_GPIO_DDR_IN (KEY_H1_GPIO_DDR &= ~BIT[KEY_H1])
- #define KEY_H1_SET() (KEY_H1_GPIO |= BIT[KEY_H1])
- #define KEY_H1_RST() (KEY_H1_GPIO &= ~BIT[KEY_H1])
- #define KEY_H1_GET() (KEY_H1_PIN&BIT[KEY_H1])
- #define KEY_H2_GPIO PORTC
- #define KEY_H2_PIN PINC
- #define KEY_H2_GPIO_DDR DDRC
- #define KEY_H2_GPIO_DDR_OUT (KEY_H2_GPIO_DDR |= BIT[KEY_H2])
- #define KEY_H2_GPIO_DDR_IN (KEY_H2_GPIO_DDR &= ~BIT[KEY_H2])
- #define KEY_H2_SET() (KEY_H2_GPIO |= BIT[KEY_H2])
- #define KEY_H2_RST() (KEY_H2_GPIO &= ~BIT[KEY_H2])
- #define KEY_H2_GET() (KEY_H2_PIN&BIT[KEY_H2])
- #define KEY_H3_GPIO PORTC
- #define KEY_H3_PIN PINC
- #define KEY_H3_GPIO_DDR DDRC
- #define KEY_H3_GPIO_DDR_OUT (KEY_H3_GPIO_DDR |= BIT[KEY_H3])
- #define KEY_H3_GPIO_DDR_IN (KEY_H3_GPIO_DDR &= ~BIT[KEY_H3])
- #define KEY_H3_SET() (KEY_H3_GPIO |= BIT[KEY_H3])
- #define KEY_H3_RST() (KEY_H3_GPIO &= ~BIT[KEY_H3])
- #define KEY_H3_GET() (KEY_H3_PIN&BIT[KEY_H3])
- #define KEY_H4_GPIO PORTC
- #define KEY_H4_PIN PINC
- #define KEY_H4_GPIO_DDR DDRC
- #define KEY_H4_GPIO_DDR_OUT (KEY_H4_GPIO_DDR |= BIT[KEY_H4])
- #define KEY_H4_GPIO_DDR_IN (KEY_H4_GPIO_DDR &= ~BIT[KEY_H4])
- #define KEY_H4_SET() (KEY_H4_GPIO |= BIT[KEY_H4])
- #define KEY_H4_RST() (KEY_H4_GPIO &= ~BIT[KEY_H4])
- #define KEY_H4_GET() (KEY_H4_PIN&BIT[KEY_H4])
- #define KEY_L1_GPIO PORTC
- #define KEY_L1_PIN PINC
- #define KEY_L1_GPIO_DDR DDRC
- #define KEY_L1_GPIO_DDR_OUT (KEY_L1_GPIO_DDR |= BIT[KEY_L1])
- #define KEY_L1_GPIO_DDR_IN (KEY_L1_GPIO_DDR &= ~BIT[KEY_L1])
- #define KEY_L1_SET() (KEY_L1_GPIO |= BIT[KEY_L1])
- #define KEY_L1_RST() (KEY_L1_GPIO &= ~BIT[KEY_L1])
- #define KEY_L1_GET() (KEY_L1_PIN&BIT[KEY_L1])
- #define KEY_L2_GPIO PORTC
- #define KEY_L2_PIN PINC
- #define KEY_L2_GPIO_DDR DDRC
- #define KEY_L2_GPIO_DDR_OUT (KEY_L2_GPIO_DDR |= BIT[KEY_L2])
- #define KEY_L2_GPIO_DDR_IN (KEY_L2_GPIO_DDR &= ~BIT[KEY_L2])
- #define KEY_L2_SET() (KEY_L2_GPIO |= BIT[KEY_L2])
- #define KEY_L2_RST() (KEY_L2_GPIO &= ~BIT[KEY_L2])
- #define KEY_L2_GET() (KEY_L2_PIN&BIT[KEY_L2])
- #define KEY_L3_GPIO PORTC
- #define KEY_L3_PIN PINC
- #define KEY_L3_GPIO_DDR DDRC
- #define KEY_L3_GPIO_DDR_OUT (KEY_L3_GPIO_DDR |= BIT[KEY_L3])
- #define KEY_L3_GPIO_DDR_IN (KEY_L3_GPIO_DDR &= ~BIT[KEY_L3])
- #define KEY_L3_SET() (KEY_L3_GPIO |= BIT[KEY_L3])
- #define KEY_L3_RST() (KEY_L3_GPIO &= ~BIT[KEY_L3])
- #define KEY_L3_GET() (KEY_L3_PIN&BIT[KEY_L3])
- #define KEY_L4_GPIO PORTC
- #define KEY_L4_PIN PINC
- #define KEY_L4_GPIO_DDR DDRC
- #define KEY_L4_GPIO_DDR_OUT (KEY_L4_GPIO_DDR |= BIT[KEY_L4])
- #define KEY_L4_GPIO_DDR_IN (KEY_L4_GPIO_DDR &= ~BIT[KEY_L4])
- #define KEY_L4_SET() (KEY_L4_GPIO |= BIT[KEY_L4])
- #define KEY_L4_RST() (KEY_L4_GPIO &= ~BIT[KEY_L4])
- #define KEY_L4_GET() (KEY_L4_PIN&BIT[KEY_L4])
- unsigned int key_n[16];
- bit key_flag=0;
- void key_scan(void)
- {
- key_flag=0;
- /*****检测第1行****************/
- KEY_H1_RST(); KEY_H2_SET();KEY_H3_SET();KEY_H4_SET();
- if(KEY_L1_GET()==0)
- {
- delay_ms(1);
- if(KEY_L1_GET()==0)
- {
- key_n[0]++;
- key_flag=1;
- }
- }
- else if(KEY_L2_GET()==0)
- {
- delay_ms(1);
- if(KEY_L2_GET()==0)
- {
- key_n[1]++;
- key_flag=1;
- }
- }
- else if(KEY_L3_GET()==0)
- {
- delay_ms(1);
- if(KEY_L3_GET()==0)
- {
- key_n[2]++;
- key_flag=1;
- }
- }
- else if(KEY_L4_GET()==0)
- {
- delay_ms(1);
- if(KEY_L4_GET()==0)
- {
- key_n[3]++;
- key_flag=1;
- }
- }
- /*****检测第2行****************/
- KEY_H1_SET(); KEY_H2_RST();KEY_H3_SET();KEY_H4_SET();
- if(KEY_L1_GET()==0)
- {
- delay_ms(1);
- if(KEY_L1_GET()==0)
- {
- key_n[4]++;
- key_flag=1;
- }
- }
- else if(KEY_L2_GET()==0)
- {
- delay_ms(1);
- if(KEY_L2_GET()==0)
- {
- key_n[5]++;
- key_flag=1;
- }
- }
- else if(KEY_L3_GET()==0)
- {
- delay_ms(1);
- if(KEY_L3_GET()==0)
- {
- key_n[6]++;
- key_flag=1;
- }
- }
- else if(KEY_L4_GET()==0)
- {
- delay_ms(1);
- if(KEY_L4_GET()==0)
- {
- key_n[7]++;
- key_flag=1;
- }
- }
- /*****检测第3行****************/
- KEY_H1_SET(); KEY_H2_SET();KEY_H3_RST();KEY_H4_SET();
- if(KEY_L1_GET()==0)
- {
- delay_ms(1);
- if(KEY_L1_GET()==0)
- {
- key_n[8]++;
- key_flag=1;
- }
- }
- else if(KEY_L2_GET()==0)
- {
- delay_ms(1);
- if(KEY_L2_GET()==0)
- {
- key_n[9]++;
- key_flag=1;
- }
- }
- else if(KEY_L3_GET()==0)
- {
- delay_ms(1);
- if(KEY_L3_GET()==0)
- {
- key_n[10]++;
- key_flag=1;
- }
- }
- else if(KEY_L4_GET()==0)
- {
- delay_ms(1);
- if(KEY_L4_GET()==0)
- {
- key_n[11]++;
- key_flag=1;
- }
- }
- /*****检测第4行****************/
- KEY_H1_SET(); KEY_H2_SET();KEY_H3_SET();KEY_H4_RST();
- if(KEY_L1_GET()==0)
- {
- delay_ms(1);
- if(KEY_L1_GET()==0)
- {
- key_n[12]++;
- key_flag=1;
- }
- }
- else if(KEY_L2_GET()==0)
- {
- delay_ms(1);
- if(KEY_L2_GET()==0)
- {
- key_n[13]++;
- key_flag=1;
- }
- }
- else if(KEY_L3_GET()==0)
- {
- delay_ms(1);
- if(KEY_L3_GET()==0)
- {
- key_n[14]++;
- key_flag=1;
- }
- }
- else if(KEY_L4_GET()==0)
- {
- delay_ms(1);
- if(KEY_L4_GET()==0)
- {
- key_n[15]++;
- key_flag=1;
- }
- }
- }
- void key_pro()
- {
- if(key_flag==0)
- {
- if(key_n[0]>0)//0
- {
- key_n[0]=0;
- input_dat(0);
- }
- else if(key_n[1]>0)//1
- {
- key_n[1]=0;
- input_dat(1);
- }
- else if(key_n[2]>0)//2
- {
- key_n[2]=0;
- input_dat(2);
- }
- else if(key_n[3]>0)//3
- {
- key_n[3]=0;
- input_dat(3);
- }
- else if(key_n[4]>0)//4
- {
- key_n[4]=0;
- input_dat(4);
- }
- else if(key_n[5]>0)//5
- {
- key_n[5]=0;
- input_dat(5);
- }
- else if(key_n[6]>0)//6
- {
- key_n[6]=0;
- input_dat(6);
- }
- else if(key_n[7]>0)//乘位
- {
- key_n[7]=0;
- input_dat(7);
- }
- else if(key_n[8]>0)//1
- {
- key_n[8]=0;
- input_dat(8);
- }
- else if(key_n[9]>0)//2
- {
- key_n[9]=0;
- input_dat(9);
- }
- else if(key_n[10]>0)//3
- {
- key_n[10]=0;
- input_dat('A');
- }
- else if(key_n[11]>0)//方式数字转换
- {
- key_n[11]=0;
- input_dat('B');
- }
- else if(key_n[12]>0)//明暗转换
- {
- key_n[12]=0;
- input_dat('C');
- }
- else if(key_n[13]>0)//0
- {
- key_n[13]=0;
- input_dat('D');
- }
- else if(key_n[14]>0)//接收
- {
- key_n[14]=0;
- input_dat('E');
- }
- else if(key_n[15]>0)//发送
- {
- key_n[15]=0;
- input_dat('F');
- }
- }
- }
- void key(void)
- {
- key_scan();
- key_pro();
- }
- /**************UART*************************/
- void USART_INIT(void)
- {
- PORTD = 0x02; // TXD(PD1)输出
- DDRD = 0x00; // RXD(PD0)输入,上拉有效
- UCSRA = 0x00; // USART初始化
- UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // 允许RXC中断,接收允许,发送允许
- // UCSRB = 0x98;
- UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
- // UCSRC = 0x86;
- UBRRH = BAUD_H; // 设置波特率,1200bps
- UBRRL = BAUD_L;
- }
- void USART_SEND(unsigned char data) // USART发送子程序
- {
- while (!(UCSRA & (1<<UDRE))); // 等待发送寄存器空
- UDR = data; // 发送数据
- }
- /**************LCD*************************/
- #define LCD_DATA_GPIO PORTA//LCD数据接口定义
- #define LCD_DATA_GPIO_DDR DDRA
- #define SET_LCD_DATA_GPIO_DDR (LCD_DATA_GPIO_DDR|=0XFF)
- #define CLR_LCD_DATA_GPIO_DDR (LCD_DATA_GPIO_DDR&=0X00)
- #define LCD_RS 5
- #define LCD_RW 6
- #define LCD_EN 7
- #define LCD_RS_GPIO PORTB
- #define LCD_RS_GPIO_DDR DDRB
- #define SET_LCD_RS_GPIO_DDR (LCD_RS_GPIO_DDR|=BIT[LCD_RS])
- #define CLR_LCD_RS_GPIO_DDR (LCD_RS_GPIO_DDR&=~BIT[LCD_RS])
- #define RS_SET() (LCD_RS_GPIO|=BIT[LCD_RS])
- #define RS_RST() (LCD_RS_GPIO&=~BIT[LCD_RS])
- #define LCD_RW_GPIO PORTB
- #define LCD_RW_GPIO_DDR DDRB
- #define SET_LCD_RW_GPIO_DDR (LCD_RW_GPIO_DDR|=BIT[LCD_RW])
- #define CLR_LCD_RW_GPIO_DDR (LCD_RW_GPIO_DDR&=~BIT[LCD_RW])
- #define RW_SET() (LCD_RW_GPIO|=BIT[LCD_RW])
- #define RW_RST() (LCD_RW_GPIO&=~BIT[LCD_RW])
- #define LCD_EN_GPIO PORTB
- #define LCD_EN_GPIO_DDR DDRB
- #define SET_LCD_EN_GPIO_DDR (LCD_EN_GPIO_DDR|=BIT[LCD_EN])
- #define CLR_LCD_EN_GPIO_DDR (LCD_EN_GPIO_DDR&=~BIT[LCD_EN])
- #define EN_SET() (LCD_EN_GPIO|=BIT[LCD_EN])
- #define EN_RST() (LCD_EN_GPIO&=~BIT[LCD_EN])
- void lcd_gpio_init(void)
- {
- SET_LCD_RS_GPIO_DDR;
- SET_LCD_RW_GPIO_DDR;
- SET_LCD_EN_GPIO_DDR;
- }
- /*****************************************************
- 函数功能:将模式设置指令或显示地址写入液晶模块
- 入口参数:dictate
- ***************************************************/
- void WriteInstruction (unsigned char dictate)
- {
- delay_ms(2);
- RS_RST(); //根据规定,RS和R/W同时为低电平时,可以写入指令
- RW_RST();
- EN_RST(); //E置低电平(根据表8-6,写指令时,E为高脉冲,
- // 就是让E从0到1发生正跳变,所以应先置"0"
- delay_us(2); //空操作两个机器周期,给硬件反应时间
- LCD_DATA_GPIO=dictate; //将数据送入P0口,即写入指令或地址
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_SET(); //E置高电平
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_RST(); //当E由高电平跳变成低电平时,液晶模块开始执行命令
- }
- /*****************************************************
- 函数功能:指定字符显示的实际地址
- 入口参数:x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
- }
- /*****************************************************
- 函数功能:将数据(字符的标准ASCII码)写入液晶模块
- 入口参数:y(为字符常量)
- ***************************************************/
- void WriteData(unsigned char y)
- {
- delay_ms(2);
- RS_SET(); //RS为高电平,RW为低电平时,可以写入数据
- RW_RST();
- EN_RST(); //E置低电平(根据表8-6,写指令时,E为高脉冲,
- // 就是让E从0到1发生正跳变,所以应先置"0"
- LCD_DATA_GPIO=y; //将数据送入P0口,即将数据写入液晶模块
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_SET(); //E置高电平
- delay_us(40); //空操作四个机器周期,给硬件反应时间
- EN_RST(); //当E由高电平跳变成低电平时,液晶模块开始执行命令
- }
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//显示一个字节
- {
- unsigned char a;
- if(hang == 1)a = 0x00;
- if(hang == 2)a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//向LCD写入数据要显示的地址
- WriteData(sign);//向LCD写入要显示的数据
- }
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD写入要显示的字符串
- {
- unsigned char a;
- if(hang == 1) a = 0x00;
- if(hang == 2) a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//写入显示的首地址
- while(1)
- {
- if(*p == '\0') break;
- WriteData(*p);
- p++;
- }
- }
- /*****************************************************
- 函数功能:对LCD的显示模式进行初始化设置
- ***************************************************/
- void LcdInitiate(void)
- {
- delay_ms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间
- WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口
- delay_ms(5); //延时5ms
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x0c); //显示模式设置:显示开,有光标,光标闪烁
- delay_ms(5);
- WriteInstruction(0x06); //显示模式设置:光标右移,字符不移
- delay_ms(5);
- WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除
- delay_ms(5);
- LCD1602_string(1,1," \0");
- }
- 终端程序
- #include <mega16.h>
- #include <delay.h>
- #define BAUD 9600 // 波特率采用9600bps
- #define CRYSTAL 4000000 // 系统时钟4MHz
- //计算和定义波特率设置参数
- #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率计算
- #define BAUD_H (unsigned char)(BAUD_SETTING>>8) // 高8位
- #define BAUD_L (unsigned char)(BAUD_SETTING) // 低8位
- unsigned char const num_str[]={"0123456789"};
- void USART_INIT(void);
- void USART_SEND(unsigned char data); // USART发送子程序
- void USART_SEND_N(unsigned char num,unsigned char *buf);
- interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中断服务
- void lcd_gpio_init(void);
- void LcdInitiate(void);
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p);
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign);
- unsigned char rx_buf[16],rx_cnt=0,rx_cnt_r=0;
- void main(void)
- {
- unsigned char dat=0,i,flag_start = 0,lcd_buf[16],lcd_cnt;
- unsigned int tim_cnt = 0,t = 0;
- USART_INIT();
- lcd_gpio_init();
- LcdInitiate();
- LCD1602_string(1,1,"Name:CDE\0");
- LCD1602_string(2,1,"Num:987654\0");
- #asm("sei") // 开中断
- while(1)
- {
- delay_ms(1);
- if(flag_start==2)
- {
-
- }
- else if(flag_start==1)
- {
-
- }
- if(rx_cnt)
- {
- if(rx_cnt == rx_cnt_r)
- {
- if(rx_buf[0]==0x09&&rx_cnt==2)
- {
- LCD1602_string(1,1," \0");
- LCD1602_string(1,1," exam is over ! \0");
- LCD1602_string(2,1," \0");
- LCD1602_string(2,1,"currut :\0");
- LCD1602_char(2,9,rx_buf[1]+'0');
- LCD1602_string(2,10," Err:\0");
- LCD1602_char(2,16,5-rx_buf[1]+'0');
- }
- else if(rx_buf[0]==0x00&&rx_cnt==10)
- {
- lcd_cnt = 0;
- for(i=0;i<3;i++)
- {
- if(rx_buf[i+1]!=('C'+i))break;
- }
- if(i==3)
- {
- for(i=0;i<6;i++)
- {
- if(rx_buf[i+4]!=(9-i))break;
- }
- }
- if(i==6)
- {
- flag_start = 1;
- LCD1602_string(1,1,"From the end of \0");
- LCD1602_string(2,1,"the exam->00:00 \0");
- //发送时间
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x01;//发送时间
- lcd_buf[lcd_cnt++] = 0x02;//发送分钟
- lcd_buf[lcd_cnt++] = 0x00;//发送秒钟
- for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);
- delay_ms(300);
- USART_SEND(0x02); //发送题1
- USART_SEND_N(15,"3+1*3+6/2= 9 ");
- delay_ms(300);
- USART_SEND(0x03); //发送题2
- USART_SEND_N(15,"5+10/5+1*1= 11");
- delay_ms(300);
- USART_SEND(0x04); //发送题3
- USART_SEND_N(15,"9-3*3+2*1= 2 ");
- delay_ms(300);
- USART_SEND(0x05); //发送题4
- USART_SEND_N(15,"12/3+8/4+2= 8 ");
- delay_ms(300);
- USART_SEND(0x06); //发送题5
- USART_SEND_N(15,"15/3+2*6-11= 6 ");
- }
- else
- {
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x00;//发送考生校验
- lcd_buf[lcd_cnt++] = 0x01;//发送错误
- for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);
- }
- }
- else if(rx_buf[0]==0x01&&rx_cnt==3)//收到开始考试指令
- {
- tim_cnt = rx_buf[1];
- tim_cnt = tim_cnt*60 + rx_buf[2];
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = rx_buf[1]/10%10+'0';
- lcd_buf[lcd_cnt++] = rx_buf[1]%10+'0';
- lcd_buf[lcd_cnt++] = 0;
- LCD1602_string(2,11,lcd_buf);
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = rx_buf[2]/10%10+'0';
- lcd_buf[lcd_cnt++] = rx_buf[2]%10+'0';
- lcd_buf[lcd_cnt++] = 0;
- LCD1602_string(2,14,lcd_buf);
-
- }
- rx_cnt = 0;
- }
- rx_cnt_r = rx_cnt;
- }
- }
- }
- interrupt [USART_RXC] void USART_RCV_INT(void) // USART接收中断服务
- {
- unsigned char data;
- data = UDR; // 接收数据
- if(rx_cnt<16)
- {
- rx_buf[rx_cnt++] = data;
- }
- }
- /**************UART*************************/
- void USART_INIT(void)
- {
- PORTD = 0x02; // TXD(PD1)输出
- DDRD = 0x00; // RXD(PD0)输入,上拉有效
- UCSRA = 0x00; // USART初始化
- UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // 允许RXC中断,接收允许,发送允许
- // UCSRB = 0x98;
- UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
- // UCSRC = 0x86;
- UBRRH = BAUD_H; // 设置波特率,1200bps
- UBRRL = BAUD_L;
- }
- void USART_SEND(unsigned char data) // USART发送子程序
- {
- while (!(UCSRA & (1<<UDRE))); // 等待发送寄存器空
- UDR = data; // 发送数据
- }
- void USART_SEND_N(unsigned char num,unsigned char *buf)
- {
- unsigned char i;
- for(i=0;i<num;i++)
- {
- USART_SEND(buf[i]);
- }
- }
- /**************LCD*************************/
- #define BIT0 0X01
- #define BIT1 0X02
- #define BIT2 0X04
- #define BIT3 0X08
- #define BIT4 0X10
- #define BIT5 0X20
- #define BIT6 0X40
- #define BIT7 0X80
- unsigned char const BIT[]={BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7};
- #define LCD_DATA_GPIO PORTA//LCD数据接口定义
- #define LCD_DATA_GPIO_DDR DDRA
- #define SET_LCD_DATA_GPIO_DDR (LCD_DATA_GPIO_DDR|=0XFF)
- #define CLR_LCD_DATA_GPIO_DDR (LCD_DATA_GPIO_DDR&=0X00)
- #define LCD_RS 5
- #define LCD_RW 6
- #define LCD_EN 7
- #define LCD_RS_GPIO PORTB
- #define LCD_RS_GPIO_DDR DDRB
- #define SET_LCD_RS_GPIO_DDR (LCD_RS_GPIO_DDR|=BIT[LCD_RS])
- #define CLR_LCD_RS_GPIO_DDR (LCD_RS_GPIO_DDR&=~BIT[LCD_RS])
- #define RS_SET() (LCD_RS_GPIO|=BIT[LCD_RS])
- #define RS_RST() (LCD_RS_GPIO&=~BIT[LCD_RS])
- #define LCD_RW_GPIO PORTB
- #define LCD_RW_GPIO_DDR DDRB
- #define SET_LCD_RW_GPIO_DDR (LCD_RW_GPIO_DDR|=BIT[LCD_RW])
- #define CLR_LCD_RW_GPIO_DDR (LCD_RW_GPIO_DDR&=~BIT[LCD_RW])
- #define RW_SET() (LCD_RW_GPIO|=BIT[LCD_RW])
- #define RW_RST() (LCD_RW_GPIO&=~BIT[LCD_RW])
- #define LCD_EN_GPIO PORTB
- #define LCD_EN_GPIO_DDR DDRB
- #define SET_LCD_EN_GPIO_DDR (LCD_EN_GPIO_DDR|=BIT[LCD_EN])
- #define CLR_LCD_EN_GPIO_DDR (LCD_EN_GPIO_DDR&=~BIT[LCD_EN])
- #define EN_SET() (LCD_EN_GPIO|=BIT[LCD_EN])
- #define EN_RST() (LCD_EN_GPIO&=~BIT[LCD_EN])
- void lcd_gpio_init(void)
- {
- SET_LCD_RS_GPIO_DDR;
- SET_LCD_RW_GPIO_DDR;
- SET_LCD_EN_GPIO_DDR;
- }
- /*****************************************************
- 函数功能:将模式设置指令或显示地址写入液晶模块
- 入口参数:dictate
- ***************************************************/
- void WriteInstruction (unsigned char dictate)
- {
- delay_ms(2);
- RS_RST(); //根据规定,RS和R/W同时为低电平时,可以写入指令
- RW_RST();
- EN_RST(); //E置低电平(根据表8-6,写指令时,E为高脉冲,
- // 就是让E从0到1发生正跳变,所以应先置"0"
- delay_us(2); //空操作两个机器周期,给硬件反应时间
- LCD_DATA_GPIO=dictate; //将数据送入P0口,即写入指令或地址
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_SET(); //E置高电平
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_RST(); //当E由高电平跳变成低电平时,液晶模块开始执行命令
- }
- /*****************************************************
- 函数功能:指定字符显示的实际地址
- 入口参数:x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
- }
- /*****************************************************
- 函数功能:将数据(字符的标准ASCII码)写入液晶模块
- 入口参数:y(为字符常量)
- ***************************************************/
- void WriteData(unsigned char y)
- {
- delay_ms(2);
- RS_SET(); //RS为高电平,RW为低电平时,可以写入数据
- RW_RST();
- EN_RST(); //E置低电平(根据表8-6,写指令时,E为高脉冲,
- // 就是让E从0到1发生正跳变,所以应先置"0"
- LCD_DATA_GPIO=y; //将数据送入P0口,即将数据写入液晶模块
- delay_us(4); //空操作四个机器周期,给硬件反应时间
- EN_SET(); //E置高电平
- delay_us(40); //空操作四个机器周期,给硬件反应时间
- EN_RST(); //当E由高电平跳变成低电平时,液晶模块开始执行命令
- }
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//显示一个字节
- {
- unsigned char a;
- if(hang == 1)a = 0x00;
- if(hang == 2)a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//向LCD写入数据要显示的地址
- WriteData(sign);//向LCD写入要显示的数据
- }
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD写入要显示的字符串
- {
- unsigned char a;
- if(hang == 1) a = 0x00;
- if(hang == 2) a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//写入显示的首地址
- while(1)
- {
- if(*p == '\0') break;
- WriteData(*p);
- p++;
- }
- }
- /*****************************************************
- 函数功能:对LCD的显示模式进行初始化设置
- ***************************************************/
- void LcdInitiate(void)
- {
- delay_ms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间
- WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口
- delay_ms(5); //延时5ms
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x0c); //显示模式设置:显示开,有光标,光标闪烁
- delay_ms(5);
- WriteInstruction(0x06); //显示模式设置:光标右移,字符不移
- delay_ms(5);
- WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除
- delay_ms(5);
- LCD1602_string(1,1," \0");
- }
复制代码
全部资料51hei下载地址:
atmega16设计电子考试系统仿真及程序.rar
(870.03 KB, 下载次数: 32)
|