- 功能用途:采用兩個單片機系統實現四則運算考試及判卷功能,具體內容包括:
⑴兩個單片機系統分別作為服務器和答題終端。服務器負責驗證考生個人信息,發送試題到終端,定時收卷及判分功能。答題終端負責輸入考生個人信息,答題,修改答案及傳送答案到服務器。 ⑵服務器驗證考生個人信息,若信息不正確則向終端發出提示信息。信息驗證正確后將試題發送到答題終端,同時開始計時。無論答題是否完成,考試時間到則強制收題。也可在考試時間尚有剩余時接收答題終端發送過來的答案。收題后進行判分工作并給出最終得分及答題情況統計信息。對回答錯誤的題目則給出原題及正確答案。 ⑶答題終端在收到試題后向考生顯示試題內容(可逐道顯示)并接受考生輸入的答案。試題顯示應具備翻頁功能以允許考生反復瀏覽試題或檢查所作答案。當考生檢查完畢且考試時間尚有剩余,允許考生向服務器發送最終答案。 ⑷實現服務器和答題終端的兩個單片機系統均應包含鍵盤和LCD液晶顯示模塊。兩個單片機系統通過串口進行通信。 機系統通過串口進行通信。 ⑴給出使用說明,包括按鍵的定義,操作方法等。 ⑵所有功能用途均可實現且各功能轉換正常(模擬5道題即可)。 ⑶考生個人信息包括考生姓名(可用拼音表示)和6位的學號。 ⑷驗收時需要演示考生個人信息不正確時的處理情況; ⑸服務器和終端都應實時顯示考試剩余時間; ⑹四則運算應覆蓋加減乘除四種運算; ⑺終端答題時,在未提交答案前應允許反復瀏覽或修改答案
O$UMNKQ3UMXY1}~KSL~J3NH.png (227.9 KB, 下載次數: 58)
下載附件
2020-4-4 17:49 上傳
終端的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.png (6.2 KB, 下載次數: 62)
下載附件
2020-4-4 18:46 上傳
全部資料51hei下載地址:
atmega16設計電子考試系統仿真及程序.rar
(870.03 KB, 下載次數: 32)
2020-4-4 17:47 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|