/******************************************************************************
*
* Copyright (C), 2012, 厦门安普利生物工程有限公司 All rights reserved.
* @file usart.c
* @brief 实现AVR USART 基本操作函数接口
*
* @version 1.0.0
* @author cyycyh
* @date 2012-06-21
* @section history
* \<author\>\<time\>\<version\>\<desc\>
* @ cyycyh 20120621 13:15 1.0.1 创建
* 本版本暂时只是实现 8 bit的帧传输 V1.0.1
* @cyycyh 20120626 9:45 1.0.2 创建
* 该版本增加对数据处理模块 V1.0.2
*
******************************************************************************/
#include "usart.h"
#include <avr/delay.h>
int USART_Flag = 0;
///////////////////////////////////////////////////////////////
////////////////////USART硬件模块处理//////////////////////////
///////////////////////////////////////////////////////////////
/*
* @brief USART 波特率初始化
* [Input] Baud : 选择所需要的波特率
* Double : 是否加倍 0 :不加倍 1 :表示加倍
* BAUD = F_CPU / (16*(UBRR + 1))
*/
void USART_Baud_Init(unsigned int Baud, int Double)
{
if (1 == Double)
{
UCSRA |= (1 << U2X);
}
UBRRL = (F_OSC/Baud/16 - 1)%256;
UBRRH = (F_OSC/Baud/16 - 1)/256;
}
/*
* @brief USART 三种中断模式选择
* [Input] inter_mode : USART 中断方式 (-1 < inter_mode < 3)
* 0 : 表示采用查询方式
* 1 : 表示接收结束中断
* 2 : 表示发送结束中断
* 3 :表示UDR为空中断
*[NOTE] 一般同一机器上使用接收为中断,发送为查询方式
*/
void USART_INT_Init(int Inter_Type)
{
UCSRB |= (1 << TXEN) | (1 << RXEN);
switch (Inter_Type)
{
case 0 : break;
case 1 : UCSRB |= (1 << RXCIE);
break;
case 2 : UCSRB |= (1 << TXCIE);
break;
case 3 : UCSRB |= (1 << UDRIE); /*为何调试助手不显示*/
break;
case 4 : UCSRB |= (1 << RXCIE) |(1 << TXCIE); /*接收能显示,但要发送时,却都停止了*/
break;
default:break;
}
}
/*
* @brief 数据帧的选择
* [Input] Frame_Type : 数据帧的确定 (-1, 5)
* 0 : 5 bit; 1 : 6 bit
* 2 : 7 bit; 3 : 8bit
* 4 : 9 bit
*/
void USART_Frame_Init(int Frame_Type)
{
switch (Frame_Type)
{
case 0 : ; /*5 bit*/
break;
case 1 : ; /*6 bit*/
break;
case 2 : ; /*7 bit*/
break;
case 3 : UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // | (1 << UPM1); /*8 bit*/
break;
case 4 : UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); /*9 bit*/
UCSRB |= (1 << UCSZ2);
break;
default: break;
}
}
/*
* @brief 是否要多机通信
* [Input] Multi : bool 类型,0 :否; 1 :是
* Multi computers communication
*/
void USART_Is_MPCM(int Multi)
{
if (1 == Multi)
{
UCSRA |= (1 << MPCM);
}
else
{
UCSRA &= ~(1 << MPCM);
}
}
/*
* @brief USART 串口初始化
* [Input]
*/
void USART_Init(unsigned int Baud, int Double,int Inter_Type, int Frame_Type)
{
cli(); /*设置前关闭总中断*/
USART_Baud_Init(Baud, Double);
USART_Is_MPCM(1);
USART_INT_Init(Inter_Type);
USART_Frame_Init(Frame_Type);
/*默认采取异步模式、正常异常模式 1 bit 停止位*/
sei(); /*设置完成开启总中断*/
}
/*
* @brief 从USART缓冲区中接收数据
* [Input] None
* [Return] 返回到接收的数据
* [Note] 这函数应用于 USART 查询接收模式
*/
unsigned char USART_Receive(void)
{
/*等待接收数据*/
while (!(UCSRA & (1<<RXC)))
{
;
}
return UDR;
}
/*
* @brief 从USART缓冲区中写入数据
* [Input] data : 要写入缓冲区的数据
* [Note] 这函数应用于USART查询发送模式
*/
void USART_Transmit(unsigned char data)
{
while (!(UCSRA & (1<<UDRE)))
{
; //等待发送缓冲器为空
}
UDR = data; // 将数据放入缓冲器,发送数据
}
/*
* @brief 从USART缓冲区中写入数据
* [Input] ptr : 要写入缓冲区的数据指针
* [Note] 这函数应用于USART查询发送模式
*/
void USART_Transmit_Str(char *ptr)
{
while (*ptr)
{
USART_Transmit(*ptr++);
}
USART_Transmit('\n');
//USART_Transmit(0xA); //换行
}
/*
* @brief 从USART缓冲区中写入数据
* [Input] ptr : 要写入缓冲区的数据指针
* [Note] 这函数应用于USART查询发送模式
*/
void USART_Transmit_Len(unsigned char *ptr, int len)
{
int i = 0;
for (i = 0; i < len; i ++)
{
USART_Transmit(*ptr++);
}
}
/*
* @brief USART接收中断处理入口函数
*/
SIGNAL(SIG_USART_RECV)
{
static int USART_Cnt = 0; /*用于中断计数*/
if ((UCSRB & (1 << RXB8)))
{
USART_Rec_Buff[0] = UDR;
if (USART_Rec_Buff[0] == 12)
{
USART_Transmit(USART_Rec_Buff[0]);
UCSRA &= ~(1 << MPCM);
}
}
else
{
USART_Rec_Buff[USART_Cnt] = UDR;
USART_Transmit(USART_Rec_Buff[USART_Cnt]);
if (USART_Cnt >= USART_Rec_Buff[0])
{
UCSRA |= (1 << MPCM);
USART_Cnt = 0;
}
else
{
USART_Cnt ++;
}
}
}
/*
* @brief USART发送中断处理入口函数
*/
SIGNAL(SIG_USART_TRANS)
{
cli();
_delay_ms(1000);
PORTA = UDR;
DDRA = 0xff;
sei();
}
/*
* @brief USART UDR为空中断处理入口函数
*/
SIGNAL(SIG_USART_DATA)
{
PORTB = ~PORTB;
DDRB |= (1 << PB1);
_delay_ms(1000);
}
///////////////////////////////////////////////////////////////
///////////USART 事物模块处理==>主要是对数据如何处理///////////
///////////////////////////////////////////////////////////////
int USART_Crc(unsigned char data[], int len)
{
unsigned char i = 0;
int total = 0;
for(i = 0; i < len; i++)
{
total += data[i];
}
if (256 == total)
{
return 0;
}
return 1;
}