|
本帖最后由 huge 于 2015-2-19 01:23 編輯
本制作程序的上位機詳見:http://www.zg4o1577.cn/bbs/dpj-31601-1.html
耗了我1個半月的時間,終于算是結束了。廢話不說,直接步入正題。
下位機的設計是以ATmega16為核心,采用時鐘芯片DS1302,RS-232串行通信接口,MAX232電平轉換芯片(因為在Proteus中串行接口電平已經轉換了,所以并沒有加入仿真中)。
/*****************************************************
【Proteus仿真效果】
- /*****************************************************
- 【CVAVR下的源程序】
- #include <mega16.h>
- #asm
- .equ __ds1302_port=0x15
- .equ __ds1302_io=7
- .equ __ds1302_sclk=6
- .equ __ds1302_rst=5
- #endasm
- #include <ds1302.h>
- #define uchar unsigned char
- uchar c0;
- uchar dis_buff[14],time[7];
- uchar roomno[50][5];
- int time100ms;
- uchar time_counter100ms,time_counter1s;
- uchar i,j,choice,room,roomnum,move,moveh,countnum,receivenum,sendnum;
- bit time100ms_ok,time1s_ok,dot0,k,key;
- //RSDA PORTC.1
- //CLK PORTC.0
- //RCK PORTC.2
- //138使能E PORTC.4
- flash uchar signature[][32]={ // "以下房間電量不足",點陣16x16,長度32字節};
- flash uchar number[][16]={ // "0 1 2 3 4 5 6 7 8 9 ",點陣8x16,長度16字節 };
- flash uchar dot[][16]={ // ":"點陣8x16,長度16字節};
- flash uchar datachars[][16]={ // "今天是年月日",點陣8x16,長度16字節};
- #ifndef RXB8
- #define RXB8 1
- #endif
- #ifndef TXB8
- #define TXB8 0
- #endif
- #ifndef UPE
- #define UPE 2
- #endif
- #ifndef DOR
- #define DOR 3
- #endif
- #ifndef FE
- #define FE 4
- #endif
- #ifndef UDRE
- #define UDRE 5
- #endif
- #ifndef RXC
- #define RXC 7
- #endif
- #define FRAMING_ERROR (1<<FE)
- #define PARITY_ERROR (1<<UPE)
- #define DATA_OVERRUN (1<<DOR)
- #define DATA_REGISTER_EMPTY (1<<UDRE)
- #define RX_COMPLETE (1<<RXC)
-
- void sendbyteR(uchar temp) //發送數據
- {
- uchar c;
- for(c=0;c<8;c++)
- {
- PORTC.1=(temp)&(0x01);
- temp=temp>>1;
- PORTC.0=0x01; //上升沿
- PORTC.0=0;
- }
- }
- void time_to_disbuffer() // 日期、時鐘、天數送顯示緩沖區函數
- {
- unsigned char i,j0=0;
- for (i=0;i<=6;i++)
- {
- dis_buff[j0++] = time[i]%10;
- dis_buff[j0++] = time[i]/10;
- }
- }
- uchar s,chartemp[10];
- flash unsigned char *disword[36];
- void disdata() //字幕緩沖函數
- {
- uchar i;
- for(i=0;i<=7;i++) disword[i]=&number[1][0];
- for(i=8;i<=13;i++) disword[i]=&datachars[i-8][0];
- for(i=14;i<=17;i++) disword[i]=&number[2*dis_buff[27-i]][0];
- disword[18]=&datachars[6][0];
- disword[19]=&datachars[7][0];
- disword[20]=&number[2*dis_buff[9]][0];
- disword[21]=&number[2*dis_buff[8]][0];
- disword[22]=&datachars[8][0];
- disword[23]=&datachars[9][0];
- disword[24]=&number[2*dis_buff[7]][0];
- disword[25]=&number[2*dis_buff[6]][0];
- disword[26]=&datachars[10][0];
- disword[27]=&datachars[11][0];
- disword[28]=&number[1][0];
- disword[29]=&number[2*dis_buff[5]][0];
- disword[30]=&number[2*dis_buff[4]][0];
- disword[31]=&dot[0][0];
- disword[32]=&number[2*dis_buff[3]][0];
- disword[33]=&number[2*dis_buff[2]][0];
- disword[34]=&number[1][0];
- disword[35]=&number[1][0];
- }
- void move_left() //字幕左移函數
- {
- uchar i;
- for(i=0;i<=9;i++)
- chartemp[i] = *(disword[i+s]+j);
- for(i=0;i<=8;i++)
- chartemp[i]=(chartemp[i]<<moveh)|(chartemp[i+1]>>(8-moveh));
- }
- void todispcase3()
- {
- choice=3;
- if(time100ms_ok)
- {
- time100ms_ok=0;
- if(++moveh>=8)
- {
- moveh=0;
- if(++s>=27) s=0;
- }
- }
- if(time1s_ok)
- {
- time1s_ok=0;
- rtc_get_date(&time[3],&time[4],&time[5]);
- rtc_get_time(&time[2],&time[1],&time[0]);
- time_to_disbuffer();
- disdata();
- }
- }
- void display(uchar diff) //掃描顯示函數
- {
- PORTC.4=0;
- switch(diff)
- {
- case 0: //顯示時間(小時,分)
- {
- sendbyteR(number[1][j]);
- sendbyteR(number[1][j]);
- sendbyteR(number[dis_buff[2]*2][j]);
- sendbyteR(number[dis_buff[3]*2][j]);
- if(dot0) sendbyteR(dot[0][j]);
- else sendbyteR(number[1][j]);
- sendbyteR(number[dis_buff[4]*2][j]);
- sendbyteR(number[dis_buff[5]*2][j]);
- sendbyteR(number[1][j]);
- break;
- }
- case 1: //顯示缺電提示字幕
- {
- sendbyteR(signature[3+4*k][j*2+1]);
- sendbyteR(signature[3+4*k][j*2]);
- sendbyteR(signature[2+4*k][j*2+1]);
- sendbyteR(signature[2+4*k][j*2]);
- sendbyteR(signature[1+4*k][j*2+1]);
- sendbyteR(signature[1+4*k][j*2]);
- sendbyteR(signature[0+4*k][j*2+1]);
- sendbyteR(signature[0+4*k][j*2]);
- break;
- }
- case 2: //顯示缺電寢室號
- {
- sendbyteR(number[1][j]);
- sendbyteR(number[(roomno[room][4])*2][j+move]);
- sendbyteR(number[(roomno[room][3])*2][j+move]);
- sendbyteR(number[(roomno[room][2])*2][j+move]);
- sendbyteR(number[(roomno[room][1])*2][j+move]);
- sendbyteR(number[(roomno[room][0])*2][j+move]);
- sendbyteR(number[1][j]);
- sendbyteR(number[1][j]);
- break;
- }
- case 3: //左移顯示時間(年,月,日,小時,分)
- {
- move_left();
- sendbyteR(chartemp[7]);
- sendbyteR(chartemp[6]);
- sendbyteR(chartemp[5]);
- sendbyteR(chartemp[4]);
- sendbyteR(chartemp[3]);
- sendbyteR(chartemp[2]);
- sendbyteR(chartemp[1]);
- sendbyteR(chartemp[0]);
- break;
- }
- }
- PORTA=j;
- PORTC.2=1;
- PORTC.2=0;
- PORTC.4=1;
- if(++j>=16) j=0;
- }
- // USART Receiver buffer
- #define RX_BUFFER_SIZE 11
- #define UART_BEGIN_STX 0xBB
- #define UART_END_STX 0xEE
- char rx_buffer[RX_BUFFER_SIZE];
- #if RX_BUFFER_SIZE <= 256
- unsigned char rx_wr_index,rx_rd_index,rx_counter;
- #else
- unsigned int rx_wr_index,rx_rd_index,rx_counter;
- #endif
- // This flag is set on USART Receiver buffer overflow
- bit rx_buffer_overflow;
- // USART Receiver interrupt service routine
- interrupt [USART_RXC] void usart_rx_isr(void)
- {
- char status,data;
- status=UCSRA;
- data=UDR;
- if(!rx_buffer_overflow)
- {
- if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
- {
- rx_buffer[rx_wr_index]=data;
- rx_wr_index++;
- switch(rx_wr_index)
- {
- case 1: // 檢驗起始字符
- if (data != UART_BEGIN_STX)
- rx_wr_index = 0;
- break;
- case 10:
- if (data !=(rx_buffer[1]^rx_buffer[4]))
- rx_wr_index = 0;
- break;
- case 11:
- rx_wr_index=0;
- if (data == UART_END_STX) rx_buffer_overflow=1;
- break;
- }
- }
- }
- }
- #ifndef _DEBUG_TERMINAL_IO_
- // Get a character from the USART Receiver buffer
- #define _ALTERNATE_GETCHAR_
- #pragma used+
- char getchar(void)
- {
- char data;
- while (rx_counter==0);
- data=rx_buffer[rx_rd_index++];
- #if RX_BUFFER_SIZE != 256
- if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
- #endif
- #asm("cli")
- --rx_counter;
- #asm("sei")
- return data;
- }
- #pragma used-
- #endif
- // USART Transmitter buffer
- #define TX_BUFFER_SIZE 11
- char tx_buffer[TX_BUFFER_SIZE];
- #if TX_BUFFER_SIZE <= 256
- unsigned char tx_wr_index,tx_rd_index,tx_counter;
- #else
- unsigned int tx_wr_index,tx_rd_index,tx_counter;
- #endif
- // USART Transmitter interrupt service routine
- interrupt [USART_TXC] void usart_tx_isr(void)
- {
- if (tx_counter)
- {
- --tx_counter;
- UDR=tx_buffer[tx_rd_index++];
- #if TX_BUFFER_SIZE != 256
- if (tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
- #endif
- }
- }
- #ifndef _DEBUG_TERMINAL_IO_
- // Write a character to the USART Transmitter buffer
- #define _ALTERNATE_PUTCHAR_
- #pragma used+
- void putchar(char c)
- {
- while (tx_counter == TX_BUFFER_SIZE);
- #asm("cli")
- if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
- {
- tx_buffer[tx_wr_index++]=c;
- #if TX_BUFFER_SIZE != 256
- if (tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
- #endif
- ++tx_counter;
- }
- else
- UDR=c;
- #asm("sei")
- }
- #pragma used-
- #endif
- // Standard Input/Output functions
- #include <stdio.h>
- // Timer 0 output compare interrupt service routine
- interrupt [TIM0_COMP] void timer0_comp_isr(void)
- {
- // Place your code here
- display(choice); //定時2ms,2ms顯示掃描一次
- if(++time_counter100ms>=50)
- {
- time_counter100ms=0; //定時100ms
- time100ms_ok=1;
- time100ms++;
- if(++time_counter1s>=10)
- {
- time_counter1s=0;
- time1s_ok=1; //定時1s
- dot0=~dot0; //秒閃爍
- }
- }
- }
- void main(void) //主函數
- {
- PORTA=0x00;
- DDRA=0x0F;
- PORTC=0x00;
- DDRC=0xF7;
- PORTD=0x00;
- DDRD=0x02;
- // Mode: CTC top=OCR0
- TCCR0=0x0B; // Timer/Counter 0 initialization
- TCNT0=0x00; // Clock source: System Clock
- OCR0=0x7C; // Clock value: 62.500 kHz
- // USART initialization
- UCSRA=0x00;
- UCSRB=0xD8; // Communication Parameters: 8 Data, 1 Stop, No Parity
- UCSRC=0x86; // USART Receiver: On,USART Transmitter: On
- UBRRH=0x00; // USART Mode: Asynchronous
- UBRRL=0x19; // USART Baud Rate: 9600
- countnum=0;
- roomnum=0; //roomnum為要顯示寢室的個數
- room=0;
- move=0;
- rtc_init(1,2,3); // 初始化DS1302
- //rtc_get_time(&time[2],&time[1],&time[0]);
- time[6]=20;time[5]=12;time[4]=11;time[3]=12;
- time[2]=0;time[1]=0;time[0]=0;
- time_to_disbuffer();
- disdata();
- choice=0;
- // Global enable interrupts
- #asm("sei")
- while (1)
- {
- // Place your code here
- if (rx_buffer_overflow)
- { // 有剛接收到數據包需要處理
- receive:
- PORTC.4=0;
- switch(rx_buffer[1])
- {
- case 0xA2:
- for(i=2;i<=8;i++)
- time[8-i]=rx_buffer[i];
- countnum=1;
- break;
- case 0xA8:
- for(i=2;i<=6;i++)
- roomno[roomnum][i-2]=rx_buffer[i];
- roomnum++;
- break;
- case 0xAF:
- receivenum=rx_buffer[2];
- TIMSK=0x00;
- time100ms=0;
- choice=0;
- room=0;
- move=0;
- countnum=0;
- roomnum=0;
- s=0;
- moveh=0;
- time100ms=0;
- break;
- default:
- sendnum=0x01;
- break;
- }
- rx_buffer_overflow = 0; // 允許接收下一個數據包
- }
-
- if(((countnum+roomnum)==receivenum)&(receivenum>0))
- {
- sendnum=0x00;
- putchar(UART_BEGIN_STX);
- putchar('AA');
- putchar(sendnum);
- for(c0=0;c0<=5;c0++) putchar('00');
- putchar('AA');
- putchar(UART_END_STX);
- TIMSK=0x02;
- }
-
- if(roomnum>0) key=1;
- else key=0;
- rtc_set_date(time[3],time[4],time[5]);
- rtc_set_time(time[2],time[1],time[0]);
- time_to_disbuffer();
- //顯示模塊處理
- //while((countnum+roomnum)==receivenum)
- while(((countnum+roomnum)==receivenum)&(receivenum>0))
- {
- if(rx_buffer_overflow) goto receive; //判斷是否更新顯示信息
- if(key) //顯示缺電提示判斷
- {
- if(time100ms<=210)
- {
- todispcase3();
- }
- else if(time100ms<=280)
- {
- choice=0;
- if(time1s_ok)
- {
- time1s_ok=0;
- rtc_get_time(&time[2],&time[1],&time[0]);
- time_to_disbuffer();
- }
- } //顯示現在時間
- else if(time100ms<=290)
- {
- k=0;
- choice=1;
- } //顯示“以下房間”
- else if(time100ms<=300)
- {
- k=1;
- choice=1;
- } //顯示“電量不足”
- else
- {
- choice=2;
- if(time100ms_ok)
- {
- time100ms_ok=0;
- if(++move>=16)
- {
- move=0;
- if(++room>=roomnum)
- {
- room=0;
- s=0;
- moveh=0;
- time100ms=0;
- time100ms_ok=0;
- }
- }
- } //顯示“缺電寢室”,1.6s換一個寢室號
- }
- }
- else
- {
- if(time100ms<=210) //只顯示現在時間
- {
- todispcase3();
- }
- else if(time100ms<=3810)
- {
- choice=0;
- if(time1s_ok)
- {
- time1s_ok=0;
- rtc_get_time(&time[2],&time[1],&time[0]);
- time_to_disbuffer();
- }
- }
- else
- {
- s=0;
- moveh=0;
- time100ms=0;
- time100ms_ok=0;
- }
- }
- }
- }
- }
復制代碼 /*****************************************************
最后效果怎么說呢,感覺在Proteus仿真中的時間會慢一點,1s并不是所謂的1s,在顯示模式的切換下也有一定的BUG。很想入手個二手的點陣屏,看看真實的效果怎樣,進一步修改。呵呵。
|
|