數據發送
流程:串口發送數據,全部數據發送完畢后,會產生一個發送中斷,所以
發送數據分為兩部分,
A、發送數據
B、中斷處理
A、發送數據
u16 Uart_Send_Data(void* buffer, u16 size)
{
if(!size) return 0;// 判斷長度是否有效
while (DMA_GetCurrDataCounter(DMA1_Channel4));// 檢查DMA發送通道內是否還有數據
if(buffer) memcpy(sendbuf, buffer,(size 》 1024?1024:size));
//DMA發送數據-要先關 設置發送長度 開啟DMA
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA1_Channel4-》CNDTR = size;// 設置發送長度
DMA_Cmd(DMA1_Channel4, ENABLE); // 啟動DMA發送
return size;
}
B、中斷處理
1)中斷處理相關準備工作
typedef enum _UartEvent_
{
E_uart_0 = 0,// 沒有事件
E_uart_tc=0x40, //發送完成
E_uart_idle=0x80, //接收完成
}UartEvent;
u16 receivelen = 0;// 聲明接收數據長度
UartEvent event;//申明一個事件參數
//清除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);
}
// 獲取一個事件,事件分為發送完成事件和接收完成事件,可以根據事件進行進行處理
UartEvent Uart_Get_Event(void)
{
UartEvent e;
if(!DMA1_Channel5-》CNDTR) Uart_Dma_Clr();// 如果產生一個事件后,接收數據通道已經沒有了緩存空間,進行清除DMA清空
return event;
}
// 清除對應的事件
void Uart_Clr_Event(UartEvent event_in)
{
event&=~event_in;
}
2) 中斷處理,當所有數據發送完畢,串口1產生一個發送完成中斷
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長度,得到接收到數據的長度
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
}
**if(USART_GetITStatus(USART1,USART_IT_TC)!= RESET) // 全部數據發送完成,產生該標記**
{
USART_ClearITPendingBit(USART1, USART_IT_TC); // 清除完成標記
DMA_Cmd(DMA1_Channel4, DISABLE); // 關閉DMA
DMA1_Channel4-》CNDTR=0; // 清除數據長度
Uart_Set_Event(E_uart_tc); //設置發送完成事件
}
}
4、接收數據
根據上圖描述,流程如下:
1、串口接收到數據
2、DMA自動取走數據
3、DMA把數據存到內存receive[1024]中
4、串口接收完畢后會產生一個空閑中斷
根據上面流程,我們接收數據需要做到兩步:
1)串口產生一個空閑中斷后,設置一個接收完成事件
中斷處理:
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長度,得到接收到數據的長度
USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除空閑中斷
}
if(USART_GetITStatus(USART1,USART_IT_TC)!= RESET) // 全部數據發送完成,產生該標記
{
USART_ClearITPendingBit(USART1, USART_IT_TC); // 清除完成標記
DMA_Cmd(DMA1_Channel4, DISABLE); // 關閉DMA
DMA1_Channel4-》CNDTR=0; // 清除數據長度
Uart_Set_Event(E_uart_tc); //設置發送完成事件
}
}
2)接收數據函數檢測事件,如果發現是接收完成事件,取走數據,并且做相關清除操作
u8 Uart_Receive_Data(u8*recbuf u16 *revLen)
{
u8 *str;
if( event & E_uart_idle) // 是否產生空閑中斷
{
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;
}
}
評論