AVR atmega16协议的制定

来源:本站
导读:目前正在解读《AVR atmega16协议的制定》的相关信息,《AVR atmega16协议的制定》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《AVR atmega16协议的制定》的详细说明。
简介:此规定的协议时通过上位机发送指令,使单片机在不同的时间内发送读取的温度值。接收器接收一个完整的数据帧后,接收到的数据驻留在接收缓冲器中,此时RXC标志。会置1(产生接收完成中断),表示接收器收到一个数据在接收缓冲器中,未被读取。当RXC为“0”时,表示数据接收器为空。

#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; //读指针指向下一个未发送的数据,如果指到了队列尾部,则回到队列头部。

}

}

提醒:《AVR atmega16协议的制定》最后刷新时间 2024-03-14 01:09:36,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《AVR atmega16协议的制定》该内容的真实性请自行鉴别。