數(shù)據(jù)發(fā)送
流程:串口發(fā)送數(shù)據(jù),全部數(shù)據(jù)發(fā)送完畢后,會產(chǎn)生一個發(fā)送中斷,所以
發(fā)送數(shù)據(jù)分為兩部分,
A、發(fā)送數(shù)據(jù)
B、中斷處理
A、發(fā)送數(shù)據(jù)
u16 Uart_Send_Data(void* buffer, u16 size)
{
if(!size) return 0;// 判斷長度是否有效
while (DMA_GetCurrDataCounter(DMA1_Channel4));// 檢查DMA發(fā)送通道內(nèi)是否還有數(shù)據(jù)
if(buffer) memcpy(sendbuf, buffer,(size 》 1024?1024:size));
//DMA發(fā)送數(shù)據(jù)-要先關 設置發(fā)送長度 開啟DMA
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA1_Channel4-》CNDTR = size;// 設置發(fā)送長度
DMA_Cmd(DMA1_Channel4, ENABLE); // 啟動DMA發(fā)送
return size;
}
B、中斷處理
1)中斷處理相關準備工作
typedef enum _UartEvent_
{
E_uart_0 = 0,// 沒有事件
E_uart_tc=0x40, //發(fā)送完成
E_uart_idle=0x80, //接收完成
}UartEvent;
u16 receivelen = 0;// 聲明接收數(shù)據(jù)長度
UartEvent event;//申明一個事件參數(shù)
//清除DMA 緩存,并終止DMA
void Uart_Dma_Clr(void)
{
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA1_Channel4-》CNDTR=0;
DMA_Cmd(DMA1_Channel5, DISABLE);
DMA1_Channel5-》CNDTR=DMASIZE ;
DMA_Cmd(DMA1_Channel5, ENABLE);
}
// 獲取一個事件,事件分為發(fā)送完成事件和接收完成事件,可以根據(jù)事件進行進行處理
UartEvent Uart_Get_Event(void)
{
UartEvent e;
if(!DMA1_Channel5-》CNDTR) Uart_Dma_Clr();// 如果產(chǎn)生一個事件后,接收數(shù)據(jù)通道已經(jīng)沒有了緩存空間,進行清除DMA清空
return event;
}
// 清除對應的事件
void Uart_Clr_Event(UartEvent event_in)
{
event&=~event_in;
}
2) 中斷處理,當所有數(shù)據(jù)發(fā)送完畢,串口1產(chǎn)生一個發(fā)送完成中斷
void Uatr1_Back_IRQHandler()
{
u8 tem;
if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)
{
tem=USART1-》SR;//先讀SR,然后讀DR才能清除
tem=USART1-》DR;
tem=tem;
Uart_Set_Event(E_uart_idle);
receivelen =DMASIZE - DMA1_Channel5-》CNDTR;// 總的buf長度減去剩余buf長度,得到接收到數(shù)據(jù)的長度
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
}
**if(USART_GetITStatus(USART1,USART_IT_TC)!= RESET) // 全部數(shù)據(jù)發(fā)送完成,產(chǎn)生該標記**
{
USART_ClearITPendingBit(USART1, USART_IT_TC); // 清除完成標記
DMA_Cmd(DMA1_Channel4, DISABLE); // 關閉DMA
DMA1_Channel4-》CNDTR=0; // 清除數(shù)據(jù)長度
Uart_Set_Event(E_uart_tc); //設置發(fā)送完成事件
}
}
4、接收數(shù)據(jù)
根據(jù)上圖描述,流程如下:
1、串口接收到數(shù)據(jù)
2、DMA自動取走數(shù)據(jù)
3、DMA把數(shù)據(jù)存到內(nèi)存receive[1024]中
4、串口接收完畢后會產(chǎn)生一個空閑中斷
根據(jù)上面流程,我們接收數(shù)據(jù)需要做到兩步:
1)串口產(chǎn)生一個空閑中斷后,設置一個接收完成事件
中斷處理:
void Uatr1_Back_IRQHandler()
{
u8 tem;
**if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)**
{
tem=USART1-》SR;//先讀SR,然后讀DR才能清除
tem=USART1-》DR;// 清除DR
tem=tem; // 防止編譯器警告
Uart_Set_Event(E_uart_idle);// 設置接收完成(空閑)事件
receivelen =DMASIZE - DMA1_Channel5-》CNDTR;// 總的buf長度減去剩余buf長度,得到接收到數(shù)據(jù)的長度
USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除空閑中斷
}
if(USART_GetITStatus(USART1,USART_IT_TC)!= RESET) // 全部數(shù)據(jù)發(fā)送完成,產(chǎn)生該標記
{
USART_ClearITPendingBit(USART1, USART_IT_TC); // 清除完成標記
DMA_Cmd(DMA1_Channel4, DISABLE); // 關閉DMA
DMA1_Channel4-》CNDTR=0; // 清除數(shù)據(jù)長度
Uart_Set_Event(E_uart_tc); //設置發(fā)送完成事件
}
}
2)接收數(shù)據(jù)函數(shù)檢測事件,如果發(fā)現(xiàn)是接收完成事件,取走數(shù)據(jù),并且做相關清除操作
u8 Uart_Receive_Data(u8*recbuf u16 *revLen)
{
u8 *str;
if( event & E_uart_idle) // 是否產(chǎn)生空閑中斷
{
str = Uart_Get_Data(revLen);
memcpy(recbuf,receivebuf,*revLen);
Uart_Clr_Event(E_uart_idle);
Uart_Dma_Clr();
return TRUE;
}
else
{
revLen = 0;
return FALSE;
}
}
評論
查看更多