此規定的協議時通過上位機發送指令,使單片機在不同的時間內發送讀取的溫度值
#define F_CPU 8000000UL
#include
#include
#include
#define BAUD 9600 //定義波特率
#define uchar unsigned char
#define uint unsigned int
#define FRAMING_ERROR _BV(FE) //接收幀出錯
#define PARITY_ERROR _BV(PE) //校驗出錯
#define DATA_OVERRUN _BV(DOR) //數據溢出
#define DATA_REGISTER_EMPTY _BV(UDRE) //數據寄存器為空,當寫入UDR(TXB)的字符被傳送到移位寄存器中時,該位置1, 表示UDR可以寫入新的數據。
#define RX_COMPLETE _BV(RXC) //接收器接收一個完整的數據幀后,接收到的數據駐留在接收緩沖器中,此時RXC標志。會置1(產生接收完成中斷),
//表示接收器收到一個數據在接收緩沖器中,未被讀取。當RXC為“0”時,表示數據接收器為空。
#define TX_BUFFER_SIZE 6 //發送緩沖器大小
//USART接收緩沖區
#define RX_BUFFER_SIZE 5 //接收緩沖器大小
uchar rx_buffer[RX_BUFFER_SIZE]={0,0,1,0,0}; //定義接收緩沖區
//定義接收緩沖區環形隊列的控制指針,rx_wr_index為寫指針,rx_rd_index為讀指針,rx_counter為存放在隊列中的已接受到字符數
#if RX_BUFFER_SIZE <256
uchar rx_wr_index,rx_rd_index,rx_counter;
#else
uint rx_wr_index,rx_rd_index,rx_counter;
#endif
//端口狀態初始化設置函數
//void Port_Init()
//{
//PORTD = 0X00; //USART 的發送接收端口分別為 PD0 和 PD1
//DDRD |= (1 << PD1); //PD0 為接收端口,置為輸入口;PD1 為發送端口,置為輸出口
//}
void Usart_Init()
{
UCSRA = 0X00;
UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //異步,數據格式 8,N,1
//UCSRC 寄存器與 UBRRH 寄存器共用相同的 I/O 地址,寫 UCSRC 時, URSEL 應設置為 1。
UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率設置
UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB |= (1 << TXEN)|(1<<RXEN)|(1<<RXCIE)|(1<<TXCIE); //接收發送接收使能,并使能發送接收標志中斷,
}
uchar rx_buffer_overflow; //接收緩沖區溢出標志
uchar recvFlag;
//接收中斷服務
ISR(USART_RXC_vect)
{
uchar status,data;
status=UCSRA; //讀取接收狀態標志位,必須先讀,當讀了UDR以后,UCSRA便自動清零了
data=UDR; //讀取USART數據寄存器
if(!recvFlag)
{
if ((status &(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRUN)) ==0)
{
rx_buffer[rx_counter]=data; //將字符填充到接收緩沖區隊列中
rx_counter++;
//Putchar(recvFlag);
//Putchar(data);
//
//if((rx_counter++)==5)
//{
//rx_counter=0;
//recvFlag=1;
//}
//Putchar(rx_counter);
//制訂協議:第一位起始位:BBH;第二位命令字:0AH代表控制數據傳送的時間,0BH代表控制溫度上下限值,
//第三位參數字,第四位校驗碼:命令字與參數字的異或,最后一位結束位:EEH
switch(rx_counter)
{
case 1: //檢驗起始位
if(data!=0XBB) rx_counter=0;break;
case 4: //校驗校驗字
if(data != rx_buffer[1]^rx_buffer[2])
//Putchar("FF");
rx_counter=0;
//Putchar(rx_buffer[0]);
//Putchar(rx_buffer[1]);
//Putchar(rx_buffer[2]);
//Putchar(rx_buffer[3]);
//Putchar(rx_buffer[4]);
break;
case 5: //校驗結束字
rx_counter=0;
if(data ==0xEE) recvFlag=1;break; //recvFlag=1表示正確接收一個數據包
}
}
}
}
//從接收隊列中讀取一個數據
uchar Getchar(void)
{
uchar data;
while(rx_counter==0); //接收緩沖區中沒有數據可以讀取,等待。
data=rx_buffer[rx_rd_index]; //讀取緩沖隊列中的數據
if(++rx_rd_index==RX_BUFFER_SIZE)
rx_rd_index=0;
cli(); //禁止中斷,這一步非常重要
--rx_counter; //隊列未讀數據個數減1.因為該變量會在接收中斷中改變,為了防止沖突,所以改動前應臨時禁止中斷。程序相當可靠
sei(); //使能中斷
return data;
}
//發送緩沖區
uchar tx_buffer[TX_BUFFER_SIZE]; //定義發送緩沖區
//定義發送緩沖區環形隊列的控制指針,tx_wr_index為寫指針,tx_rd_index為讀指針,tx_counter為存放在隊列中的已接受到字符數
uchar tx_wr_index,tx_rd_index,tx_counter;
//向USART發送緩沖區寫一個字符
void Putchar(unsigned char c)
{
while(tx_counter==TX_BUFFER_SIZE); //如果發送隊列滿,等待
cli(); //禁止中斷
if (tx_counter||((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if(++tx_wr_index==TX_BUFFER_SIZE)
tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
sei();
}
ISR(USART_TXC_vect)
{
if(tx_counter) //發送隊列中還未發送的數據
{
--tx_counter; //未發送數據減1。
UDR = tx_buffer[tx_rd_index]; //發送一個數據。
if(++tx_rd_index==TX_BUFFER_SIZE)
tx_rd_index=0; //讀指針指向下一個未發送的數據,如果指到了隊列尾部,則回到隊列頭部。
}
}