STM32 串口DMA方式接收
1.RCC(復(fù)位和時(shí)鐘控制寄存器)初始化,啟用GPIO、DMA、USART時(shí)鐘。
2.NVIC(嵌套向量中斷控制寄存器)初始化,完成各個(gè)硬件中斷的配置。
3.USART初始話,配置串口,設(shè)置DMA通道等。
4.DMA初始化,完成DMA的配置。
最后是使能USART和DMA。下面是通過(guò)DMA的方式從串口USART1接收數(shù)據(jù),STM32工作后串口數(shù)據(jù)由DMA控制器接收存到指定buffer,讀取數(shù)據(jù)直接從DMA buffer中讀取即可。發(fā)送數(shù)據(jù)采用非DMA方式,首先將待發(fā)送的數(shù)據(jù)存入到發(fā)送隊(duì)列,然后在任務(wù)循環(huán)中將隊(duì)列中的數(shù)據(jù)發(fā)送給USART1。實(shí)例代碼如下:
[cpp] view plaincopy
//**********************************************************************************************
// STM32F10x USART Test
// compiler: Keil UV3
// 2011-03-28 , By friehood
//**********************************************************************************************
static int8u rDMABuffer[64]; // DMA buffer
static int16u rDMARear = sizeof(rDMABuffer);
static int8u USART_RevBuf[64]; // 串口接收buffer
static int8u USART_SndBuf[64]; // 串口發(fā)送buffer
static int8u Head=0,Tail=0; // 發(fā)送buffer的頭尾
// 串口任務(wù)
void Task_USART(void)
{
int16u end;
if (USART1->SR & (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE))
{
USART_ReceiveData(USART1);
}
// DMA接收
end = DMA_GetCurrDataCounter(DMA1_Channel5);
/*if((sizeof(rDMABuffer)-end)>0)
dbgprt("DMA available datalen=%d/n",sizeof(rDMABuffer)-end); */
while(rDMARear != end)
{
USART_receive(rDMABuffer[sizeof(rDMABuffer)-rDMARear]);
if (!(--rDMARear))
{
rDMARear = sizeof(rDMABuffer);
}
}
//發(fā)送
if(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET)
{
int8u chr;
// 從發(fā)送隊(duì)列取出一個(gè)字符
if(PopFront(&chr))
{
USART_SendData(USART1, chr);
dbgprt("USART_SendData:0x%02x/n",chr);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{
}
}
}
}
// USART串口初始化
void dev_USART_init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 Channel5 (triggered by USART1 Rx event) Config */ //參見 STM32 datasheet
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)rDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(rDMABuffer);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//配置IO: GPIOA9和GPIOA10分別作為串口TX、RX端。 見STM32 datasheet
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStructure);
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART1 DMA Rxrequest */
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
/* Enable DMA1 Channel5 */
DMA_Cmd(DMA1_Channel5, ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
// 向串口發(fā)送數(shù)據(jù)
void USART_send(const int8u *pBuf, int8u len)
{
int i;
if(pBuf == NULL)
{
return;
}
// 將數(shù)據(jù)壓入到發(fā)送隊(duì)列
dbgprt("USART_PushBack:");
for(i=0;i
PushBack(*pBuf);
dbgprt("0x%02x ",*pBuf);
pBuf++;
}
dbgprt("/n");
}
// 向發(fā)送隊(duì)列尾部插入一個(gè)字節(jié)
void PushBack(int8u byte)
{
USART_SndBuf[Tail++]= byte;
if(Tail >= ARRAYSIZE(USART_SndBuf))
Tail = 0;
if(Tail == Head)
Head = Tail+1;
}
// 從發(fā)送隊(duì)列頭部取出一個(gè)字節(jié)
bool PopFront(int8u *byte)
{
if(Head >= ARRAYSIZE(USART_SndBuf))
Head = 0;
if(Head == Tail)
return FALSE;
*byte = USART_SndBuf[Head++];
return TRUE;
}
// 處理接收到的串口數(shù)據(jù)
void USART_receive(int8u byte)
{
// Treate received data
// Place Code here
// ...
}
// CRC校驗(yàn)
bool CheckCRC(const int8u *str, int8u len, const int8u *crcstr)
{
int8u checkSum;
if(str == NULL || crcstr== NULL)
return FALSE;
GetCRC(str,len,&checkSum);
if(checkSum != *crcstr)
return FALSE;
else
return TRUE;
}
// 獲取CRC
bool GetCRC(const int8u *str, int8u len, int8u *crcstr)
{
int8u i;
int8u checkSum;
if(str == NULL || crcstr== NULL)
return FALSE;
checkSum = *str;
for(i=1; i
checkSum ^= *(str+i);
}
*crcstr = checkSum;
return TRUE;
}
評(píng)論