- 功能用途:采用兩個(gè)單片機(jī)系統(tǒng)實(shí)現(xiàn)四則運(yùn)算考試及判卷功能,具體內(nèi)容包括:
⑴兩個(gè)單片機(jī)系統(tǒng)分別作為服務(wù)器和答題終端。服務(wù)器負(fù)責(zé)驗(yàn)證考生個(gè)人信息,發(fā)送試題到終端,定時(shí)收卷及判分功能。答題終端負(fù)責(zé)輸入考生個(gè)人信息,答題,修改答案及傳送答案到服務(wù)器。 ⑵服務(wù)器驗(yàn)證考生個(gè)人信息,若信息不正確則向終端發(fā)出提示信息。信息驗(yàn)證正確后將試題發(fā)送到答題終端,同時(shí)開(kāi)始計(jì)時(shí)。無(wú)論答題是否完成,考試時(shí)間到則強(qiáng)制收題。也可在考試時(shí)間尚有剩余時(shí)接收答題終端發(fā)送過(guò)來(lái)的答案。收題后進(jìn)行判分工作并給出最終得分及答題情況統(tǒng)計(jì)信息。對(duì)回答錯(cuò)誤的題目則給出原題及正確答案。 ⑶答題終端在收到試題后向考生顯示試題內(nèi)容(可逐道顯示)并接受考生輸入的答案。試題顯示應(yīng)具備翻頁(yè)功能以允許考生反復(fù)瀏覽試題或檢查所作答案。當(dāng)考生檢查完畢且考試時(shí)間尚有剩余,允許考生向服務(wù)器發(fā)送最終答案。 ⑷實(shí)現(xiàn)服務(wù)器和答題終端的兩個(gè)單片機(jī)系統(tǒng)均應(yīng)包含鍵盤(pán)和LCD液晶顯示模塊。兩個(gè)單片機(jī)系統(tǒng)通過(guò)串口進(jìn)行通信。 機(jī)系統(tǒng)通過(guò)串口進(jìn)行通信。 ⑴給出使用說(shuō)明,包括按鍵的定義,操作方法等。 ⑵所有功能用途均可實(shí)現(xiàn)且各功能轉(zhuǎn)換正常(模擬5道題即可)。 ⑶考生個(gè)人信息包括考生姓名(可用拼音表示)和6位的學(xué)號(hào)。 ⑷驗(yàn)收時(shí)需要演示考生個(gè)人信息不正確時(shí)的處理情況; ⑸服務(wù)器和終端都應(yīng)實(shí)時(shí)顯示考試剩余時(shí)間; ⑹四則運(yùn)算應(yīng)覆蓋加減乘除四種運(yùn)算; ⑺終端答題時(shí),在未提交答案前應(yīng)允許反復(fù)瀏覽或修改答案
終端的atmega16單片機(jī)電路連接如圖所示。復(fù)位端口連一個(gè)上拉電阻,下接一個(gè)按鍵,按鍵按下時(shí),終端單片機(jī)復(fù)位,能使終端的顯示屏回到初始的界面。在引腳XTAL1和XTAL2上外接石英晶體和電容組成的諧振回路,配合片內(nèi)的OSC振蕩電路構(gòu)成振蕩源。 終端的顯示屏設(shè)計(jì)如圖所示,里面有預(yù)置的姓名和學(xué)號(hào),只有當(dāng)服務(wù)器輸入的和終端預(yù)置的一致時(shí)才能進(jìn)入系統(tǒng)。 終端的初始頁(yè)面 通過(guò)驗(yàn)證進(jìn)入系統(tǒng)后終端會(huì)開(kāi)始計(jì)時(shí)并 答題結(jié)束之后,終端會(huì)顯示正確和錯(cuò)誤的題目個(gè)數(shù) 顯示剩余時(shí)間,如果驗(yàn)證失敗則保持初 在時(shí)間規(guī)定內(nèi),考生可自己提交答案。超出時(shí)間的 始頁(yè)面不變。 話,則系統(tǒng)強(qiáng)制收卷 客戶端單片機(jī)與終端單片機(jī)有相似的地方的這里不做贅述。 客戶端鍵盤(pán)展示 鍵盤(pán)完成輸入姓名學(xué)號(hào)、答題功能。旁邊還有四個(gè)按鍵,可以實(shí)現(xiàn)在答題的時(shí)候,上下翻查看題目,答題有誤的情況下清除原有答案,和作答完畢時(shí)提交答案的功能。 客戶端功能展示 初始頁(yè)面如圖所示,要求輸入姓名學(xué)號(hào),輸入有誤則會(huì)顯示“有一個(gè)錯(cuò)誤,請(qǐng)重新輸入” 輸入正確則會(huì)進(jìn)入考試系統(tǒng) 顯示考試開(kāi)始,計(jì)時(shí)并顯示剩余的時(shí)間。這里我們準(zhǔn)備了5道題目,按上下鍵可以翻動(dòng)題目清除可以清除答案 考試結(jié)束服務(wù)端會(huì)顯示正確和錯(cuò)誤的題目個(gè)數(shù)。 此時(shí)按上下鍵可以查看所有題目和答案 。
單片機(jī)源程序如下:
用戶端
- #include <mega16.h>
- #include <delay.h>
- #define BAUD 9600 // 波特率采用9600bps
- #define CRYSTAL 4000000 // 系統(tǒng)時(shí)鐘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};
- //計(jì)算和定義波特率設(shè)置參數(shù)
- #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率計(jì)算
- #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發(fā)送子程序
- interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中斷服務(wù)
- 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") // 開(kāi)中斷
- 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;//發(fā)送考生信息
- 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;//發(fā)送剩余時(shí)間
- lcd_buf[lcd_cnt++] = tim_cnt/60;//發(fā)送剩余分鐘
- lcd_buf[lcd_cnt++] = tim_cnt%60;//發(fā)送剩余秒鐘
- 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)//收到開(kāi)始考試指令
- {
- 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接收中斷服務(wù)
- {
- unsigned char data;
- data = UDR; // 接收數(shù)據(jù)
- 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;
- /*****檢測(cè)第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;
- }
- }
- /*****檢測(cè)第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;
- }
- }
- /*****檢測(cè)第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;
- }
- }
- /*****檢測(cè)第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)//方式數(shù)字轉(zhuǎn)換
- {
- key_n[11]=0;
- input_dat('B');
- }
- else if(key_n[12]>0)//明暗轉(zhuǎn)換
- {
- 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)//發(fā)送
- {
- 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中斷,接收允許,發(fā)送允許
- // UCSRB = 0x98;
- UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
- // UCSRC = 0x86;
- UBRRH = BAUD_H; // 設(shè)置波特率,1200bps
- UBRRL = BAUD_L;
- }
- void USART_SEND(unsigned char data) // USART發(fā)送子程序
- {
- while (!(UCSRA & (1<<UDRE))); // 等待發(fā)送寄存器空
- UDR = data; // 發(fā)送數(shù)據(jù)
- }
- /**************LCD*************************/
- #define LCD_DATA_GPIO PORTA//LCD數(shù)據(jù)接口定義
- #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;
- }
- /*****************************************************
- 函數(shù)功能:將模式設(shè)置指令或顯示地址寫(xiě)入液晶模塊
- 入口參數(shù):dictate
- ***************************************************/
- void WriteInstruction (unsigned char dictate)
- {
- delay_ms(2);
- RS_RST(); //根據(jù)規(guī)定,RS和R/W同時(shí)為低電平時(shí),可以寫(xiě)入指令
- RW_RST();
- EN_RST(); //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
- // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
- delay_us(2); //空操作兩個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- LCD_DATA_GPIO=dictate; //將數(shù)據(jù)送入P0口,即寫(xiě)入指令或地址
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_SET(); //E置高電平
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_RST(); //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
- }
- /*****************************************************
- 函數(shù)功能:指定字符顯示的實(shí)際地址
- 入口參數(shù):x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- WriteInstruction(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
- }
- /*****************************************************
- 函數(shù)功能:將數(shù)據(jù)(字符的標(biāo)準(zhǔn)ASCII碼)寫(xiě)入液晶模塊
- 入口參數(shù):y(為字符常量)
- ***************************************************/
- void WriteData(unsigned char y)
- {
- delay_ms(2);
- RS_SET(); //RS為高電平,RW為低電平時(shí),可以寫(xiě)入數(shù)據(jù)
- RW_RST();
- EN_RST(); //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
- // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
- LCD_DATA_GPIO=y; //將數(shù)據(jù)送入P0口,即將數(shù)據(jù)寫(xiě)入液晶模塊
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_SET(); //E置高電平
- delay_us(40); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_RST(); //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
- }
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//顯示一個(gè)字節(jié)
- {
- unsigned char a;
- if(hang == 1)a = 0x00;
- if(hang == 2)a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//向LCD寫(xiě)入數(shù)據(jù)要顯示的地址
- WriteData(sign);//向LCD寫(xiě)入要顯示的數(shù)據(jù)
- }
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD寫(xiě)入要顯示的字符串
- {
- unsigned char a;
- if(hang == 1) a = 0x00;
- if(hang == 2) a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//寫(xiě)入顯示的首地址
- while(1)
- {
- if(*p == '\0') break;
- WriteData(*p);
- p++;
- }
- }
- /*****************************************************
- 函數(shù)功能:對(duì)LCD的顯示模式進(jìn)行初始化設(shè)置
- ***************************************************/
- void LcdInitiate(void)
- {
- delay_ms(15); //延時(shí)15ms,首次寫(xiě)指令時(shí)應(yīng)給LCD一段較長(zhǎng)的反應(yīng)時(shí)間
- WriteInstruction(0x38); //顯示模式設(shè)置:16×2顯示,5×7點(diǎn)陣,8位數(shù)據(jù)接口
- delay_ms(5); //延時(shí)5ms
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x0c); //顯示模式設(shè)置:顯示開(kāi),有光標(biāo),光標(biāo)閃爍
- delay_ms(5);
- WriteInstruction(0x06); //顯示模式設(shè)置:光標(biāo)右移,字符不移
- delay_ms(5);
- WriteInstruction(0x01); //清屏幕指令,將以前的顯示內(nèi)容清除
- delay_ms(5);
- LCD1602_string(1,1," \0");
- }
- 終端程序
- #include <mega16.h>
- #include <delay.h>
- #define BAUD 9600 // 波特率采用9600bps
- #define CRYSTAL 4000000 // 系統(tǒng)時(shí)鐘4MHz
- //計(jì)算和定義波特率設(shè)置參數(shù)
- #define BAUD_SETTING (unsigned int)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1) // 波特率計(jì)算
- #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發(fā)送子程序
- void USART_SEND_N(unsigned char num,unsigned char *buf);
- interrupt [USART_RXC] void USART_RCV_INT(void); // USART接收中斷服務(wù)
- 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") // 開(kāi)中斷
- 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");
- //發(fā)送時(shí)間
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x01;//發(fā)送時(shí)間
- lcd_buf[lcd_cnt++] = 0x02;//發(fā)送分鐘
- lcd_buf[lcd_cnt++] = 0x00;//發(fā)送秒鐘
- for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);
- delay_ms(300);
- USART_SEND(0x02); //發(fā)送題1
- USART_SEND_N(15,"3+1*3+6/2= 9 ");
- delay_ms(300);
- USART_SEND(0x03); //發(fā)送題2
- USART_SEND_N(15,"5+10/5+1*1= 11");
- delay_ms(300);
- USART_SEND(0x04); //發(fā)送題3
- USART_SEND_N(15,"9-3*3+2*1= 2 ");
- delay_ms(300);
- USART_SEND(0x05); //發(fā)送題4
- USART_SEND_N(15,"12/3+8/4+2= 8 ");
- delay_ms(300);
- USART_SEND(0x06); //發(fā)送題5
- USART_SEND_N(15,"15/3+2*6-11= 6 ");
- }
- else
- {
- lcd_cnt = 0;
- lcd_buf[lcd_cnt++] = 0x00;//發(fā)送考生校驗(yàn)
- lcd_buf[lcd_cnt++] = 0x01;//發(fā)送錯(cuò)誤
- for(i=0;i<lcd_cnt;i++)USART_SEND(lcd_buf[i]);
- }
- }
- else if(rx_buf[0]==0x01&&rx_cnt==3)//收到開(kāi)始考試指令
- {
- 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接收中斷服務(wù)
- {
- unsigned char data;
- data = UDR; // 接收數(shù)據(jù)
- 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中斷,接收允許,發(fā)送允許
- // UCSRB = 0x98;
- UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8 Data, 1 Stop, No Parity
- // UCSRC = 0x86;
- UBRRH = BAUD_H; // 設(shè)置波特率,1200bps
- UBRRL = BAUD_L;
- }
- void USART_SEND(unsigned char data) // USART發(fā)送子程序
- {
- while (!(UCSRA & (1<<UDRE))); // 等待發(fā)送寄存器空
- UDR = data; // 發(fā)送數(shù)據(jù)
- }
- 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數(shù)據(jù)接口定義
- #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;
- }
- /*****************************************************
- 函數(shù)功能:將模式設(shè)置指令或顯示地址寫(xiě)入液晶模塊
- 入口參數(shù):dictate
- ***************************************************/
- void WriteInstruction (unsigned char dictate)
- {
- delay_ms(2);
- RS_RST(); //根據(jù)規(guī)定,RS和R/W同時(shí)為低電平時(shí),可以寫(xiě)入指令
- RW_RST();
- EN_RST(); //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
- // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
- delay_us(2); //空操作兩個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- LCD_DATA_GPIO=dictate; //將數(shù)據(jù)送入P0口,即寫(xiě)入指令或地址
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_SET(); //E置高電平
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_RST(); //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
- }
- /*****************************************************
- 函數(shù)功能:指定字符顯示的實(shí)際地址
- 入口參數(shù):x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- WriteInstruction(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
- }
- /*****************************************************
- 函數(shù)功能:將數(shù)據(jù)(字符的標(biāo)準(zhǔn)ASCII碼)寫(xiě)入液晶模塊
- 入口參數(shù):y(為字符常量)
- ***************************************************/
- void WriteData(unsigned char y)
- {
- delay_ms(2);
- RS_SET(); //RS為高電平,RW為低電平時(shí),可以寫(xiě)入數(shù)據(jù)
- RW_RST();
- EN_RST(); //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,
- // 就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置"0"
- LCD_DATA_GPIO=y; //將數(shù)據(jù)送入P0口,即將數(shù)據(jù)寫(xiě)入液晶模塊
- delay_us(4); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_SET(); //E置高電平
- delay_us(40); //空操作四個(gè)機(jī)器周期,給硬件反應(yīng)時(shí)間
- EN_RST(); //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
- }
- void LCD1602_char(unsigned char hang,unsigned char lie,unsigned char sign)//顯示一個(gè)字節(jié)
- {
- unsigned char a;
- if(hang == 1)a = 0x00;
- if(hang == 2)a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//向LCD寫(xiě)入數(shù)據(jù)要顯示的地址
- WriteData(sign);//向LCD寫(xiě)入要顯示的數(shù)據(jù)
- }
- void LCD1602_string(unsigned char hang,unsigned char lie,unsigned char const *p)//向LCD寫(xiě)入要顯示的字符串
- {
- unsigned char a;
- if(hang == 1) a = 0x00;
- if(hang == 2) a = 0x40;
- a = a + lie - 1;
- WriteAddress(a);//寫(xiě)入顯示的首地址
- while(1)
- {
- if(*p == '\0') break;
- WriteData(*p);
- p++;
- }
- }
- /*****************************************************
- 函數(shù)功能:對(duì)LCD的顯示模式進(jìn)行初始化設(shè)置
- ***************************************************/
- void LcdInitiate(void)
- {
- delay_ms(15); //延時(shí)15ms,首次寫(xiě)指令時(shí)應(yīng)給LCD一段較長(zhǎng)的反應(yīng)時(shí)間
- WriteInstruction(0x38); //顯示模式設(shè)置:16×2顯示,5×7點(diǎn)陣,8位數(shù)據(jù)接口
- delay_ms(5); //延時(shí)5ms
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x38);
- delay_ms(5);
- WriteInstruction(0x0c); //顯示模式設(shè)置:顯示開(kāi),有光標(biāo),光標(biāo)閃爍
- delay_ms(5);
- WriteInstruction(0x06); //顯示模式設(shè)置:光標(biāo)右移,字符不移
- delay_ms(5);
- WriteInstruction(0x01); //清屏幕指令,將以前的顯示內(nèi)容清除
- delay_ms(5);
- LCD1602_string(1,1," \0");
- }
復(fù)制代碼
全部資料51hei下載地址:
atmega16設(shè)計(jì)電子考試系統(tǒng)仿真及程序.rar
(870.03 KB, 下載次數(shù): 32)
2020-4-4 17:47 上傳
點(diǎn)擊文件名下載附件
|