一、ATmega16的串口
ATmega16包含一个通用同步和异步串行接收器和转发器(USART),分别和端口D(PD0和1)、端口B(PB0)的管脚复用,如下图所示。
二、串口通信原理
异步通讯,双方必须事先约定好通信参数,一般有:比特率、数据位、校验位、停止位。
异步正常操作、8位数据格式、无校验、1位停止位、双机通信模式、允许发送器和接收器、允许USART接收完成中断、波特率9600波特,总线时钟为8MHz。
1、设定USART波特率寄存器UBRR中分频因子。写UBRRH,再写UBRRL。
2、更新USART控制和状态寄存器A(UCSRA).
3、更新USART控制和状态寄存器B(UCSRB)来允许发送器、接收器,以及是否允许发送中断和接收中断等。
4、更新USART控制和状态寄存器C(UCSRC),选择异步工作模式、无校验、1位停止位长度、与UCSRnB共同确定数据位数。
三、接线原理图
四、源代码
帧头B 文字1 文字2 帧尾Z
#include <iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define Get_Bit(val, bitn) (val &(1<<(bitn)) )
uint rev_buff[2];
uint Serial_RxFlag;
void delay(unsigned int a)//延迟函数
{
unsigned int j;
while(--a!=0)
{
for(j=0;j<120;j++);
}
}
void uart_init(void)
{
UCSRB=0x00; //禁止发送器和接收器,禁止串口中断
UCSRA=0b00100000; //各标志位清零,双机通信模式,无加速波特率
UCSRC=0b10000110; //异步模式,无奇偶校验,1位停止位,8位数据位
UBRRH=0x00;
UBRRL=0x33;
UCSRB=0x98; //使能发送完成中断,使能发送器和接收器
}
void uart_send_1byte(uchar send_char)
{
while(!(UCSRA&(1<<UDRE)));//等待发送缓冲器为空
UDR=send_char; //向发送缓冲器写入1byte数据,启动发送
}
void main(void)
{
DDRC|=BIT(0); //PD0为输出
DDRB&=~BIT(0); //PB0为输入
CLI(); //关总断
uart_init(); //串口初始化
SEI(); //开总中断
while(1)
{
if(Serial_GetRxFlag() == 1)
{
uart_send_1byte(rev_buff[0]);
uart_send_1byte(rev_buff[1]);
}
}
}
#pragma interrupt_handler uart_rx_isr:12
void uart_rx_isr(void)
{
uchar rx_data;
static uint RxState = 0;
static uint pRxPacket = 0;
rx_data=UDR; //读接收缓冲器
if (RxState == 0)
{
if ( rx_data == 'B')
{
RxState = 1;
pRxPacket = 0;
}
}
else if (RxState == 1)
{
rev_buff[pRxPacket] = rx_data;
pRxPacket ++;
if (pRxPacket >= 4)
{
RxState = 2;
}
}
else if (RxState == 2)
{
if (rx_data == 'Z')
{
RxState = 0;
Serial_RxFlag = 1;
}
}
}
uint Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1;
}
return 0;
}
五、实现发送两个文字
注意:打开虚拟串口仿真软件,定义两个串口进行互连,在仿真时选择一个串口号,打开串口助手选择另外一个串口号,注意波特率一致防止传输出现乱码现象。