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

📄 usart.c

📁 Avr单片机半双工模式Usart驱动
💻 C
字号:
/*                ****ROBOCON 2009 | BUPT TEAM*******
 * ------------------------------------------------------------------------
 * FileName   : usart.c
 * Version    : 1.01
 * Biref      : USART Driver(use queue, Half Mode)
 * 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
 *
 * ------------------------------------------------------------------------
 */

#include "config.h"
#include <stdlib.h>
#ifdef USART_H_INCLUDED

static Queue usart_send0, usart_recv0;
const Usart USART0 = {
		&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, &usart_send0, &usart_recv0
};
static Queue usart_send1, usart_recv1;
const Usart USART1 = {
		&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, &usart_send1, &usart_recv1
};

/*+ Usart Mode Control */

/* Switch Usart Mode(Recv/Send) */
void usart_mode_switch(const Usart *usart, UsartMode mode){
	switch(mode){
	case usart_mode_send:
		*usart->ucsrb = (_BV(TXEN)|_BV(TXCIE));
		break;
	case usart_mode_recv:
		*usart->ucsrb = (_BV(RXEN)|_BV(RXCIE));
		break;
	case usart_mode_stop:
		*usart->ucsrb = 0;
		break;
	}
}

/* Detect Usart Mode(From Hardware)*/
UsartMode get_usart_mode(const Usart *usart){
	if(bit_is_set(*usart->ucsrb, TXEN)){
		loop_until_bit_is_set(*usart->ucsra, UDRE);
		return usart_mode_send;
	}
	else if(bit_is_set(*usart->ucsrb, RXEN)){
		return usart_mode_recv;
	}
	else{
		return usart_mode_stop;
	}
}
/*- Usart Mode Control */

/* Usart Initialization
 * Enter Usart (Recv) Mode
 * Setup Buffering Queue */
void usart_init(const Usart* usart, UINT16 ubrr){
	*usart->ucsrb = 0x00;
	*usart->ucsra = 0x00;
	*usart->ucsrc = 0x06;
	*usart->ubrrl = ubrr & 0x00ff;
	*usart->ubrrh = ubrr >> 8;
	usart_mode_switch(usart, usart_mode_recv);
	q_init( usart->send_buf,
			(Q_DATA_TYPE*)malloc(sizeof(Q_DATA_TYPE)*UART_SENDBUF_SIZE),
			UART_SENDBUF_SIZE
	);
	q_init( usart->recv_buf,
			(Q_DATA_TYPE*)malloc(sizeof(Q_DATA_TYPE)*UART_RECVBUF_SIZE),
			UART_SENDBUF_SIZE
	);
}

/*+ Usart Transfer Methods */
void usart_tx_isr(const Usart* usart){
	if(!q_empty(usart->send_buf))
		*usart->udr = q_popfront(usart->send_buf);
	else{
		usart_mode_switch(usart, usart_mode_recv);
	}
}

void inline usart_tx_start(const Usart *usart)
{
	if(get_usart_mode(usart) == usart_mode_recv){
		usart_mode_switch(usart, usart_mode_send);
		*usart->udr = q_popfront(usart->send_buf);
	}
	else if((*usart->ucsra&(1<<UDRE)) && !q_empty(usart->send_buf)){
		*usart->udr = q_popfront(usart->send_buf);
	}
}

void usart_putc(const Usart* usart, char c)
{
	while(q_full(usart->send_buf));
	q_pushback(usart->send_buf, c);
	usart_tx_start(usart);
}

void usart_puts(const Usart *usart, const char *buf)
{
	if(*buf == '\0')
		return;
	usart_putc(usart, *buf);
	++buf;
	while(*buf)
	{
		while(q_full(usart->send_buf));
		q_pushback(usart->send_buf, *buf);
		++ buf;
	}
	usart_putc(usart, 0x0d);
}

/*- Usart Transfer Methods */

/*+ Usart Recieve Methods */
/*
 * Called in usart_rx_interrupt
 * If Buffer Overflowed, Will corrupt previous data
 */
void usart_rx_isr(const Usart* usart){
	q_pushback(usart->recv_buf, *usart->udr);
}

/*
 * Get Char from usart
 * If Buffer is empty, Will wait
 */
char usart_getc(const Usart* usart)
{
	while(q_empty(usart->recv_buf));
	return( q_popfront(usart->recv_buf) );
}

/* Simply Wait \0 to end input*/
int  usart_gets(const Usart *usart, char *buf)
{
	char recv;
	int  i = 0;
	recv = usart_getc(usart);
	while(recv != '#'){
		buf[i] = recv;
		recv = usart_getc(usart);
		++ i;
	}
	buf[i] = '\0';
	return i;
}

/* Clear all Usart Buffer Data */
int  usart_flush(const Usart *usart, char *buf){
	return q_flush(usart->recv_buf, buf);
}
/*- Usart Recieve Methods */

/*+ Usart File */
#ifdef _STDIO_H_
static int
usart_putchar(char c, FILE* file){
	usart_putc(file->udata, c);
	return 0;
}

static int
usart_getchar(FILE* file){
	return usart_getc(file->udata);
}

FILE*
usart_get_stream(const Usart *usart){
	FILE *stream;
	stream = fdevopen(usart_putchar, usart_getchar);
	stream->udata = (void*)usart;
	return stream;
}

void inline
usart_setup_stream(const 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 + -