⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usart.c.svn-base

📁 AVR单片机下
💻 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 + -