📄 usart.c.svn-base
字号:
/****ROBOCON 2009 | BUPT TEAM*******
* ------------------------------------------------------------------------
* FileName : usart.c
* Version : 1.01
* Brief : USART Driver
* Code by : Leaf
* Date : Dec.08 2008
* Dependence : Queue
* Note : modify basic transfer function into a Object Method
* Usart Object Contains Information for Uart Port
* Half Mode Communication
* Switch to Send mode, Recv mode if free
* Usart Puts will have better performances
* sendOver信号量
* 初始值 - DONE
* 开始发送时 - PEND
* 发送结束时 - DONE
* Apr 23去掉了发送数据准备的缓冲区。
* Apr 23去掉了接受数据的缓冲区。
*
*
* ------------------------------------------------------------------------
*/
#include "lib_bupt.h"
#include <stdlib.h>
#ifdef USART_H_INCLUDED
static Mutex u0RecvSignal, u1RecvSignal;
static Mutex u1SendOver, u0SendOver;
static Mutex u0SendLock, u1SendLock;
Usart USART0 = {
&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0,
0, &u0RecvSignal, &u0SendOver, &u0SendLock
};
Usart USART1 = {
&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1,
0, &u1RecvSignal, &u1SendOver, &u1SendLock
};
/*+ Usart Mode Control */
void usartGetLock( Usart *u )
{
AvrXWaitSemaphore( u->sendLock );
}
void usartUnLock( Usart *u )
{
AvrXSetSemaphore( u->sendLock );
}
/* 串口模式切换( 发送/接收/全双工/停止 ) */
void usartSetMode(Usart *usart, UsartMode mode){
switch(mode){
case usart_mode_send:
loop_until_bit_is_set(*usart->ucsra, UDRE);
*usart->ucsrb = (_BV(TXEN));
break;
case usart_mode_recv:
*usart->ucsrb = (_BV(RXEN)|_BV(RXCIE));
break;
case usart_mode_dual:
*usart->ucsrb = (_BV(RXEN)|_BV(RXCIE)|_BV(TXEN));
break;
case usart_mode_stop:
*usart->ucsrb = 0;
break;
}
}
/* 检查当前串口状态 */
UsartMode usartGetMode(Usart *usart){
if(bit_is_set(*usart->ucsrb, TXEN)){
return usart_mode_send;
}
else if(bit_is_set(*usart->ucsrb, RXEN)){
return usart_mode_recv;
}
else{
return usart_mode_stop;
}
}
/*- Usart Mode Control */
/* 初始化, 分配缓冲区, 只能调用一次,否则会产生内存泄漏 */void usartInit(Usart* usart, Ubrr ubrr){
cli();
*usart->ucsrb = 0x00;
*usart->ucsra = 0x00;
*usart->ucsrc = 0x06;
*usart->ubrrl = ubrr & 0x00ff;
*usart->ubrrh = ubrr >> 8; usartFlush( usart ); AvrXSetSemaphore( usart->sendOver );
AvrXSetSemaphore( usart->sendLock );
usartSetMode(usart, usart_mode_dual);
sei();
}
/*设置波特率*/
void usartSetBaudrate(Usart *usart, UINT32 baudrate){
cli();
UINT16 ubrr = UBRR_FROM_BAUD(baudrate);
*usart->ubrrl = ubrr & 0x00ff;
*usart->ubrrh = ubrr >> 8;
sei();
}
/*设置停止位*/
void usartSetStopBits(Usart *u, UINT8 stopbits)
{
if(stopbits > 1){
SBI(*u->ucsrc, USBS);
}
else{
CBI(*u->ucsrc, USBS);
}
}
/*+ Usart Transfer Methods */
/* 串口发送中断,如果缓冲队中有数据则发送下一个数据。
* 如果缓冲区空了,则释放sendOver信号量 */
static void inline entxci(Usart *u){
SBI((*u->ucsrb), UDRE);
}
static void inline ditxci(Usart *u){
CBI((*u->ucsrb), UDRE);
}
void inline usartTxIsr(Usart* usart){
ditxci(usart);
AvrXIntSetSemaphore( usart->sendOver );
}
/* 等待数据发送结束,即sendOver信号量 */
void usartWaitSend(Usart *usart){
return;
}
/* 输出单个字符,并启动发送器。如果缓冲区满,则等当前数据全部发送完毕 */
void usartPutc(Usart* usart, char c)
{
entxci(usart);
AvrXWaitSemaphore( usart->sendOver );
*usart->udr = c;
}
/* 串口输出字串,\0结尾 */
void usartSendString(Usart *usart, const char *buf){
while(*buf)
{
usartPutc( usart, *buf );
++ buf;
}
}
/*串口输出字串, 指定长度*/
int usartWrite(Usart *usart, const void *buf, size_t size){
if(size <= 0){
return 0;
}
size_t i;
for(i = 0; i < size; ++i){
usartPutc(usart, ((UINT8*)buf)[i]);
}
usartWaitSend(usart);
return i;
}
/*串口输出字串,加\13(CR)为换行符*/
void usartPuts(Usart *usart, const char *buf)
{
usartSendString( usart, buf );
usartPutc(usart, 0x0d);
}
/*- Usart Transfer Methods */
/*+ Usart Recieve Methods */
static void inline enrxci(Usart *u)
{
SBI( (*u->ucsrb), RXCIE );
}
static void inline dirxci(Usart *u)
{
CBI( (*u->ucsrb), RXCIE );
}
/*
* Called in usart_rx_interrupt
* If Buffer Overflowed, Will corrupt previous data
* 在AvrX环境下,接收中断时,如果有人等待着,则释放recvSignal
*/
void inline usartRxIsr(Usart* usart){
dirxci( usart );
usart->recv_buf = *usart->udr;
AvrXIntSetSemaphore( usart->recvSignal );
enrxci( usart );
}
/* 从串口读取一个字符,如果没有人来发,则会等待着, 这是串口数据的唯一出口
* 在AvrX环境下,如果当前缓冲区没有数据,当前任务进入挂起状态,等待recvSignal */
char usartGetc(Usart* usart)
{
AvrXWaitSemaphore( usart->recvSignal );
return usart->recv_buf;
}
/*读入指定长度的数据*/
int usartRead(Usart *usart, void *buf, size_t size){
int i = 0;
UINT8 *dest = (UINT8 *)buf;
for(i = 0; i < size; ++i){
dest[i] = usartGetc(usart);
}
return i;
}
/*读入\0结尾的数据*/
int usartGets(Usart *usart, char *buf)
{
int i = 0;
do{
buf[i] = usartGetc(usart);
}while(buf[i] != '\0');
return i;
}
/*从串口读入一个以换行符结尾的字串*/
int usartReadline(Usart *usart, char *recv){
int i = 0;
do{
recv[i] = usartGetc(&USART0);
if(recv[i] == 10 || recv[i] == 13){
if(i == 0){
continue;
}
recv[i] = '\0';
break;
}
++ i;
}while( True ); //stop when meet line feed
return i;
}
/* Flush all Usart Buffer Data */
void usartFlush( Usart *usart ){
AvrXResetSemaphore(usart->recvSignal);
}
/* Clear all Usart Buffer Data */
void usartRecvBufclear(Usart *usart){
AvrXResetSemaphore(usart->recvSignal);
}
/*- Usart Recieve Methods */
/*+ Usart File
* 就是使对串口也能执行标准的输入/输出操作
*/
#ifdef _STDIO_H_
static int
usart_putchar(char c, FILE* file){
usartPutc(file->udata, c);
return 0;
}
static int
usart_getchar(FILE* file){
return usartGetc(file->udata);
}
FILE*
usart_get_stream(Usart *usart){
FILE *stream;
stream = fdevopen(usart_putchar, usart_getchar);
stream->udata = (void*)usart;
return stream;
}
void inline
usart_setup_stream(Usart *usart, FILE* stream){
fdev_setup_stream(stream, usart_putchar, usart_getchar, 3);
stream->udata = (void *)usart;
}
#endif
/*- Usart File */
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -