📄 m16_usart.c
字号:
/*===================================================================
CopyLeft(CL) FORVERE Late Lee
All rights NOT reserved
版权所无,翻版不究,但请保留此处信息。
http://www.cnbolgs.com/latelee
latelee@163.com
*文件名: 串口通信测试程序
*文件说明: 实现多种格式收发
*版本: v1.0
*芯片: ATmega16
*晶振: 内部 7372800MHz晶振
*作者: Late Lee
*日期: 2009年1月26日 已丑年初一晚
*编译环境: UltraEdit+WinAVR20080610(gcc 4.3.0) 经仿真测试
*说明: 下面是一些说明和笔记:
模式说明:
// M1:8位数据位,1位停止位,无校验
// M2:8位数据位,1位停止位,奇校验
// M3:8位数据位,2位停止位,无校验
// M4:8位数据位,2位停止位,偶校验
// M5:9位数据位,1位停止位,无校验
// M6:9位数据位,1位停止位,奇校验
// M7:9位数据位,2位停止位,无校验
// M8:9位数据位,2位停止位,偶校验
此次修改了关于自定义类型的一些小问题,AVRGCC建议用其定义的类型。
// 测试笔记:
1、未添加中断处理部分
2、严重声明:在发送、接收数据处理时很不合理!如果真的要分8位和9位传送,
则分开写就可以了。 2009-1-24 23:00
3、两芯片仿真时9位数据发送不正常,未与PC仿真,2009-1-24 23:05
4、usart_receive9()编译有警告,不知原因。2009-1-25 18:40
5、解决警告问题,if语句有些表达得不好,9位数据收发测试正常 1-26 21:07
====================================================================*/
#include "M16_USART.h"
/*------------------------------------------------------
关于波特率的设置,还是直接赋给寄存器比较好,减少CPU工作量
--------------------------------------------------------*/
// 形参为波特率
void usart_init_baud(uint16 baud)
{
// UBRRH = (uint8)(baud>>8); //high
// UBRRL = (uint8)baud; //low
#ifdef U2XX // 倍速
UCSRA |= (1<<U2X);
UBRRL= (F_CPU/baud/8-1)%256;
UBRRH= (F_CPU/baud/8-1)/256;
#else
UCSRA &= ~(1<<U2X);
UBRRL= (F_CPU/baud/16-1)%256; // OK here
UBRRH= (F_CPU/baud/16-1)/256;
#endif
//////////////////////////////////////////////
#if METHOD == 1
UCSRC = (1<<URSEL) | (3<<UCSZ0); //8位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 2
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //8位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 3
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 4
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 5
UCSRC = (1<<URSEL)|(3<<UCSZ0); //9位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 6
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //9位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 7
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 8
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#endif
}
// 用库函数设置
void usart_init_std(void)
{
// 利用库函数设置
UBRRH= UBRRH_VALUE;
UBRRL= UBRRL_VALUE;
#ifdef U2XX // 倍速
UCSRA |= (1<<U2X);
#else
UCSRA &= ~(1<<U2X);
#endif
//////////////////////////////////////////////
#if METHOD == 1
UCSRC = (1<<URSEL) | (3<<UCSZ0); //8位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 2
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //8位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 3
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 4
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 5
UCSRC = (1<<URSEL)|(3<<UCSZ0); //9位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 6
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //9位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 7
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 8
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#endif
}
// 无形参,波特率直接赋给UBRRH和UBRRL
void usart_init(void)
{
#ifdef U2XX // 倍速
UCSRA |= (1<<U2X);
UBRRH= 0;
UBRRL= 0x0B; // 些处添加 38400
#else
UCSRA &= ~(1<<U2X);
UBRRH= 0;
UBRRL= 0x0B;
#endif
//////////////////////////////////////////////
#if METHOD == 1
UCSRC = (1<<URSEL) | (3<<UCSZ0); //8位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 2
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //8位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 3
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 4
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //8位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN); // 使能发送接收
#elif METHOD == 5
UCSRC = (1<<URSEL)|(3<<UCSZ0); //9位数据位,1位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 6
UCSRC = (1<<URSEL) | (3<<UPM0) | (3<<UCSZ0); //9位数据位,1位停止位,奇校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 7
UCSRC = (1<<URSEL) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,无校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#elif METHOD == 8
UCSRC = (1<<URSEL) | (2<<UPM0) | (1<<USBS) |(3<<UCSZ0); //9位数据位,2位停止位,偶校验
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<UCSZ2); // 使能发送接收
#endif
}
// 8位发送
void usart_transmit8(uint8 data)
{
while ( !(UCSRA & (1<<UDRE)) ) // 不为空,等之
;
UDR = data;
}
// 9位发送
void usart_transmit9(uint16 data)
{
while ( !(UCSRA & (1<<UDRE)) ) // 不为空,等之
;
UCSRB &= ~(1<<TXB8); // 先清零
if (data & 0x0100) // 第9位为1
UCSRB |= (1<<TXB8);
UDR = data;
}
// 发送字符串
void usart_sendstring(uint8 *string)
{
while (*string)
{
usart_transmit8(*string++);
}
usart_transmit8(0x0d);
usart_transmit8(0x0a); // 最后发送回车换行
}
// 8位接收
uint8 usart_receive8(void)
{
while ( !(UCSRA & (1<<RXC)) )
;
return UDR;
}
// 9位接收
uint16 usart_receive9(void)
{
uint16 status,resulth,resultl;
while ( !(UCSRA & (1<<RXC)) )
;
status = UCSRA;
resulth = UCSRB;
resultl = UDR;
if ((uint8)status & ((1<<FE) | (1<<DOR) | (1<<PE))) // 如果出现某些错误
return -1;
resulth = (resulth>>1) & 0x01;
return ((resulth<<8) | resultl);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -