基于隊(duì)列的UART通信模塊
/********************************
基于隊(duì)列的Mega8UART通信驅(qū)動(dòng)程序
文件名:uart.c
編譯:WinAVR-20070122
硬件:CA-M8X
時(shí)鐘:外部4MHz
*******************************/
#include
#include
#include"queue.h"
#defineUART_BUF_SIZE16//發(fā)送和接收緩沖長度
HQUEUEg_SendQueue;//發(fā)送隊(duì)列句柄
HQUEUEg_RecvQueue;//接收隊(duì)列句柄
uint8_tg_SendBuffer[UART_BUF_SIZE];//發(fā)送緩沖
uint8_tg_RecvBuffer[UART_BUF_SIZE];//接收緩沖
//接收中斷SIG_UART_RECV
ISR(USART_RXC_vect)
{
uint8_tc=UDR;
QueueInput(&g_RecvQueue,c);
}
//發(fā)送寄存器空中斷
ISR(USART_UDRE_vect)
{
if(QueueGetDataCount(&g_SendQueue)>0)//如果發(fā)送緩沖隊(duì)列不空
{
UDR=QueueOutput(&g_SendQueue);//發(fā)送一字節(jié)
}
else//否則關(guān)閉發(fā)送中斷
{
UCSRB&=~_BV(UDRIE);//關(guān)閉數(shù)據(jù)空中斷
}
}
////////////以下為本模塊三個(gè)接口函數(shù)///////////////////////////
//初始化
voidUartInit(void)
{
//UART硬件初始化
UCSRB=0;
UBRRH=0;
UBRRL=25;//96004MHz
UCSRB=(1<
//創(chuàng)建發(fā)送/接收隊(duì)列
QueueCreate(&g_SendQueue,g_SendBuffer,UART_BUF_SIZE);
QueueCreate(&g_RecvQueue,g_RecvBuffer,UART_BUF_SIZE);
}
//讀接收緩沖內(nèi)的數(shù)據(jù),buf為讀取緩沖,size為buf能接收的最大長度,返回實(shí)際接收的長度
uint8_tUartRecv(uint8_t*buf,uint8_tsize)
{
uint8_ti;
for(i=0;i
if(QueueGetDataCount(&g_RecvQueue)>0)
{
cli();//以下的隊(duì)列操作不可被中斷
buf[i]=QueueOutput(&g_RecvQueue);
sei();//中斷重新允許
}
else
{
break;
}//ifelse
}//for
returni;//返回讀到的數(shù)據(jù)字節(jié)數(shù)
}
//發(fā)送數(shù)據(jù),buf為發(fā)送數(shù)據(jù)緩沖器,size為要發(fā)送的長度
voidUartSend(uint8_t*buf,uint8_tsize)
{
uint8_ti;
cli();//以下的隊(duì)列操作不可被中斷
for(i=0;i
sei();//中斷重新允許
UCSRB|=_BV(UDRIE);//數(shù)據(jù)空中斷允許
}
//////////////////////////////////////////////////////////
uart.h:
//uart.h
#ifndefUART_H
#defineUART_H
voidUartInit(void);
uint8_tUartRecv(uint8_t*buf,uint8_tsize);
voidUartSend(uint8_t*buf,uint8_tsize);
#endif
queue.c:
/********************************
隊(duì)列管理模塊
文件名:queue.c
編譯:WinAVR-20070122
芯藝設(shè)計(jì)室2004-2007版權(quán)所有
轉(zhuǎn)載請(qǐng)保留本注釋在內(nèi)的全部內(nèi)容
WEB:http://www.chipart.cn
Email:changfutong@sina.com
*******************************/
#include
#include"queue.h"
//向隊(duì)列插入一字節(jié)
voidQueueInput(PHQUEUEQ,uint8_tdat)
{
if(Q->data_count
{
Q->pBuffer[Q->in_index]=dat;//寫入數(shù)據(jù)
Q->in_index=(Q->in_index+1)%(Q->buf_size);//調(diào)整入口地址
Q->data_count++;//調(diào)整數(shù)據(jù)個(gè)數(shù)(此操作不可被中斷)
}
else
{
if(Q->error<255)
Q->error++;
}
}
//從隊(duì)列讀出一字節(jié)
uint8_tQueueOutput(PHQUEUEQ)
{
uint8_tRet=0;
if(Q->data_count>0)
{
Ret=Q->pBuffer[Q->out_index];//讀數(shù)據(jù)
Q->out_index=(Q->out_index+1)%(Q->buf_size);//調(diào)整出口地址
Q->data_count--;
}
returnRet;
}
//獲得隊(duì)列中數(shù)據(jù)個(gè)數(shù)
uint8_tQueueGetDataCount(PHQUEUEQ)
{
returnQ->data_count;
}
//清空隊(duì)列,執(zhí)行時(shí)不可被中斷
voidQueueClear(PHQUEUEQ)
{
Q->in_index=0;
Q->out_index=0;
Q->data_count=0;
Q->error=0;
}
//初始化一隊(duì)列
voidQueueCreate(PHQUEUEQ,uint8_t*buffer,uint8_tbuf_size)
{
Q->pBuffer=buffer;
Q->buf_size=buf_size;
QueueClear(Q);
}
queue.h:
//queue.h
#ifndefQUEUE_H_
#defineQUEUE_H_
//隊(duì)列數(shù)據(jù)結(jié)構(gòu)
typedefstructQUEUE_S
{
uint8_tin_index;//入隊(duì)地址
uint8_tout_index;//出隊(duì)地址
uint8_tbuf_size;//緩沖區(qū)長度
uint8_t*pBuffer;//緩沖
volatileuint8_tdata_count;//隊(duì)列內(nèi)數(shù)據(jù)個(gè)數(shù)
uint8_terror;
}HQUEUE,*PHQUEUE;
voidQueueInput(PHQUEUEQ,uint8_tdat);
uint8_tQueueOutput(PHQUEUEQ);
uint8_tQueueGetDataCount(PHQUEUEQ);
voidQueueClear(PHQUEUEQ);
voidQueueCreate(PHQUEUEQ,uint8_t*buffer,uint8_tbuf_size);
#endif