#ifndef uchar
#define uchar unsigned char
#define uint unsigned int
#endif
//__CONFIG(0x2129)
bit rec_flag //串口中断标志位,有串口中断,置1
uchar uartdata //串口数据保存到此位置中
void Uart_char(uchar dat)//串口发送一个数据
/*************************************************************
函数原型:void main(void)
功能:等待串口发送中断到来,将接收到的设计再通过串口发回
*************************************************************/
void main(void)
{
TRISB1=1
TRISB2=1
SPBRG=0X19 //设置波特率为9600BPS
TXSTA=0X24 //使能串口发送,选择高速波特率
RCSTA=0X90 //使能串口工作,连续接收
RCIE=0X1 //使能接收中断
GIE=0X1 //开放全局中断
PEIE=0X1 //使能外部中断
//INTCON=0X00
/* while(1) //查询模式下
{
RCIE=1
while(RCIF==0)
RCIE=0
Send_char(RCREG)
}
*/
while(1) //中断模式下,等待中断的到来
{
if(rec_flag==1) //如果接收中断到来
{
rec_flag=0//接收标志清零
Uart_char(uartdata)//将接收来的数据发送到串口
}
}
}
/**********************************************
函数原型:void Uart_char(uchar dat)
功能:将dat数据通过串口传送出去
**********************************************/
void Uart_char(uchar dat)
{
TXREG=dat //将dat数据存入TXREG
// TXEN=1 //启动发送,TSR开始移位 *** 作。
while (TRMT==0) //判断是否TSR发送完毕,未完等待。
// TXEN=0 //关发送功能,防止TXREG空时,TXIF产生置位
}
/**********************************************
函数原型:void interrupt usart(void)
功能:串口接收到数据,接受发来的数据将接
收到数据标志位rec_flag置1
**********************************************/
void interrupt usart(void)
{
if(RCIF) //判断是否为串口接收中断
{
rec_flag = 1
//RCIF=0
uartdata = RCREG// 接收数据并存储
//TXREG=recdata //把接收到的数据发送回去
}
}
这段程序应该对你有用
首先你要知道,UART不是与ARM体系有关,而是与具体的ARM体系CPU有关。就是说不同的CPU的UART控制器是不一样的
这个程序只能给你一个思路了
有些CPU这些发送,接收中断是可以在寄存器直接设置一个阀值的
比如你的发送缓存为8个字节,接收也是8个字节
你可以设置,当发送缓存里的数据少于1的时候就产生中断
当接收缓存里数据大于4时,就产生中断
目前很多CPU都可以直接设置内部的UART寄存器来完成这个配置
如果没有UART控制器来完成。就是说你的UART发送和接收都是自己控制的
你可以在自己的发送,接收的中断处理程序里面模拟一个缓存,来实现这些功能。我想这个应该不成问题吧
就是2个全局变量记录缓存的用量分别记录接收和发送
还有2个全局数组,比如8个字节,用来缓存接收发送的数据
你的UART中断程序如果判断到是接收,首先把数据放到缓存,然后接收缓存计数+1,判断是否超过某一个阀值,如果是的话,就做一些自定义的事情
发送是同样的道理
一.熟悉AVR单片机UART资源,首先从波特率和帧说起波特率:与51不同有单独的波特率发生器,不需要定时器来产生,节省了资源
波特率计算公式,这里我采用IccAVR的配置功能,直接计算生成
单片机支持的模式:异步正常模式,异步倍数模式,和同步模式,一般选第一种模式
帧格式:起始位+数据位(5-9位可选)+校验位(可选)+停止位(1、2位) 空闲
o ********* P 1 1
通讯电路空闲时为高电平
二、大概了解了下硬件资源后,就要了解软硬件的桥梁—寄存器了
1.数据寄存器:数据来了要有个接受的地方吧,数据发送要有个数据发送的信封吧。
这就是数据寄存器 UDR (RXB和TXB) 物理上为分开的,地址上是一样的。就像写信和接信时,你家的地址只
有同一个地址一样,但是写信和别人发给你的信封却有2个一样。使用时自动控制的。
数据寄存器为空时才能发送数据,否则会无效。数据进入后,进入移位寄存器,由引脚TXD一位位发出。
2.控制和状态寄存器 UCSRA
RXC TXC UDREFEDOR PE U2X MPCM
接受完成置1 发送完成置1 数据为空标志帧错误1 接受数据 校验位错误 倍速模式 多机通信
读取数据清0 中断时自动清0 数据完全到移 溢出1 1 1 地址位
位寄存器中1
UCSRB 设置相关中断的允许
RXCIETXCIE UDRIERXEN TXEN UXSZ2 RXB8TXB8
接受中断允许 发送中断允许 空中断允许 数据接受允许 数据发送允许 位数设置 接受第9位
RXEN,TXEN设置时会改变时普通IO口,或者是当做复用口用,在发送数据时设置下,数据全部发送后才生效
RXB8,TXB8需要先读写出
UCSRC
URSEL UMSELUPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL
寄存器选择 工作模式校验方式 停止位和上面的UXSZ2设置
写时需要设为11异步 数据个数
存在共用寄存器 00禁止11奇10偶 0为1个1为2个
波特率寄存器:UBRRL UBRRH
UBRRH和UCSRC共用 了底4位 加上UBRRL共12位 设置后正在传的数据会被打断
需要注意URSEL的设置 :0 写入的比特率高4位
1 写入的是寄存器的内容
读UBRRH,第一次是比特率的内容 在连续的2个时钟周期内再读一次就是UCRSC的内容
使用时可以查速查表,直接用ICCAVR生成工具即可。
三,相关 *** 作 等练习个程序后补上
1 初始化 关全局中断
TXC RXC看数据是否完成 发送数据前TXC必须请零
把数据放入到发送缓冲器即可 UDR中 5-8位
2 注意下空中断 允许后需要不断写数据 否则一直不断的中断产生 一般禁止就可以了
TXEN 设置0后 所有数据发送后生效 然后就当普通IO口用了
禁止接受 会立即 丢失数据
四一些总线标准
RS232 9针D型接口
1 -3 ~-25 0 3-25V
需要使用电平转换电路 MAX232
五.工业设计中的串口
这里如果大家看到了还是注意下比较好 ,网上写的不多的,我也是从工程实践和查找大量的参考书中总结的
设计思路是基于状态机,并自定义了协议,同时协议中使用了CRC校验,和简易的加密技术
思路是:主从方式,上位机发送数据包,下位机在中断中接受,接受数据时要一位位的确认,并不断进行切换,发送的位置状态,把初步确认的数据放到接受缓冲器里,等所有的数据接收好了,程序进入大循环了,就执行主程序中加入uart *** 作函数,这个函数首先判断主机发送的命令和设置是否接受完成,在完成的状态下进行校验正确性,校验后,根据主机命令,组装数据包和存贮主机的设置数据,并把需要发送的数据包或设置完成数据包放在需要发送的数据缓冲区,接着改变下此时的状态:为我组好了,准备发送数据了,接着触发中断,可以直接往串口发个数据即可,正常发送后,单片机会执行其他程序,等上位机接受到这个触发数据后,下位机会中断,中断程序会根据状态,一位位的发生缓冲区的数据,直到所有的数据发送完成,发送完成后还要置位到接受数据状态0。
我的环境是atmega128
初始化
uchar LED_Temp=0xFF
uchar OUT_temp=0x04
static uchar Uart_Status
static uchar R_Data_Lenth
uchar Tx_Buf[TxBufSize]
uchar Rx_Buf[RxBufSize]
uchar *P_Uart_Rx
uchar *P_Uart_Tx
uchar Rx_Count
uchar Tx_Count
void Uart_Init(void)
{
//UCSR0B = 0x00//先关闭
UCSR0A=0x00
UCSR0C=0x06//8 DATA ,1 STOP, NO PARITY
UCSR0B = (1< // RXCIE=1TXCIE=1UDREIE=0RXEN=1TXEN=1
Com_baudrate (9600)
P_Uart_Tx=Tx_Buf//缓冲区指针定义
P_Uart_Rx=Rx_Buf
Uart_Status=0 //开始时状态为接受起始位状态,其实这里是因为我在程序中用了通信协议
//本篇为基础,就把协议的内容删去了,仅仅提供了能运行的最简单的框架
SEI()//re-enable interrupts
}
// 函数说明:波特率设置
void Com_baudrate (unsigned int baudrate)
{
unsigned int tmp
tmp= 8000000/baudrate/16-1
UBRR0H=(unsigned char)(tmp>>8)
UBRR0L=(unsigned char)tmp
}
// 函数说明:串口接收中断函数
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)
{
//这里填写串口中断处理的内容,可以添加协议,使用状态机就可以了
//把接收到得内容放在缓冲区,然后再创建个处理缓冲区数据的函数,直接放在主循环中即可
}
//函数说明:串口发送完成中断函数
#pragma interrupt_handler uart0_tx_isr:iv_USART0_TXC
void uart0_tx_isr(void)
{
//发送数据的处理函数
}
// 函数说明:uart进程函数 ,放在大循环中
void Uart_Process(void)
{
//接收到得数据,再具体的在系统中实现,比如上位机的监控,或者传输数据等
}
//函数说明:uart测试程序
void Uart_Test(uchar data)
{
UDR0 = 0x01//发送数据
}
//- 功能描述:串口发送字节的函数
//- 函数属性:外部,使用户使用
//- 参数说明:mydata:要发送的一个字节
// - 返回说明:无
// - 注:发送一个字节,是串口发送的基础 *** 作
void UART_Send_Byte(unsigned char mydata)
{
// UCSR0B = (1< UCSR0B &= ~((1< while(!(UCSR0A &(1< //等待发送缓冲区为空
UDR0 = mydata
// delay_nms(5)
UCSR0B |= (1<//改的时候不要影响其它寄存器位,开串口中断
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)