|
本帖最后由 mmik 于 2018-6-14 16:51 編輯
最近在做一個STM32單片機(jī)的項目,用到串口通信功能。但是目前網(wǎng)上的帖子比較零碎現(xiàn)在整理一份完整的代碼發(fā)到論壇中。希望能幫到用到的朋友。
關(guān)鍵步驟:
1、初始化串口。
2、初始化DMA通道。
3、配置串口中斷,當(dāng)發(fā)生IDLE中斷時處理一次DMA數(shù)據(jù)。
4、配置DMA中斷,當(dāng)發(fā)生DMA接收完成時處理一次DMA數(shù)據(jù)。
上代碼:
初始化串口:
// 通用端口初始化參數(shù)
GPIO_InitTypeDef GPIO_InitStructure;
// 串口初始化參數(shù)
USART_InitTypeDef USART_InitStructure;
// 中斷向量初始化參數(shù)
NVIC_InitTypeDef NVIC_InitStructure;
// 啟用GPIO總線時鐘
// STM32F1系列GPIO時鐘都在APB2總線
RCC_APB2PeriphClockCmd(uartDef->portAPBxParam, ENABLE);
// 啟用串口總線時鐘
// uart1 在APB2總線,uart2~5 在APB1總線
if (APB1 == uartDef->uartAPBx)
{
RCC_APB1PeriphClockCmd(uartDef->uartAPBxParam, ENABLE);
}
else if (APB2 == uartDef->uartAPBx)
{
RCC_APB2PeriphClockCmd(uartDef->uartAPBxParam, ENABLE);
}
// 設(shè)置串口TX發(fā)送口
GPIO_InitStructure.GPIO_Pin = uartDef->txPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽輸出
GPIO_Init(uartDef->txGPIO, &GPIO_InitStructure); //初始化GPIOA.9
// 設(shè)置串口RX接收口
GPIO_InitStructure.GPIO_Pin = uartDef->rxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(uartDef->rxGPIO, &GPIO_InitStructure);
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = uartDef->uartDcb.baudrate; //串口波特率,一般設(shè)置為9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(uartDef->port, &USART_InitStructure); //初始化串口
USART_ITConfig(uartDef->port, USART_IT_RXNE, ENABLE); //開啟接收中斷
USART_ITConfig(uartDef->port, USART_IT_IDLE, ENABLE); //開啟空閑中斷
//USART NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = uartDef->NVIC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //搶占優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
USART_Cmd(uartDef->port, ENABLE); //使能串口
// 配置DMA收發(fā)
DMA_Configuration(port);
//// 配置DMA
DMA_InitTypeDef DMA_InitStructure;
//使能DMA傳輸
//
if((0x0400 & (u32)DMA_CHx))
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
}
else
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
DMA_Cmd(DMA_CHx, DISABLE);
DMA_DeInit(DMA_CHx); //將DMA的通道寄存器重設(shè)為缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外設(shè)ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA內(nèi)存基地址
DMA_InitStructure.DMA_DIR = dmaDir; //數(shù)據(jù)傳輸方向,從內(nèi)存讀取發(fā)送到外設(shè)
DMA_InitStructure.DMA_BufferSize = bufferSize; //DMA通道的DMA緩存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設(shè)地址寄存器不變
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內(nèi)存地址寄存器遞增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //數(shù)據(jù)寬度為8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //數(shù)據(jù)寬度為8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常緩存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x擁有高優(yōu)先級
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x沒有設(shè)置為內(nèi)存到內(nèi)存?zhèn)鬏?br />
DMA_Init(DMA_CHx,&DMA_InitStructure); //根據(jù)DMA_InitStruct中指定的參數(shù)初始化DMA的通道USART1_Tx_DMA_Channel所標(biāo)識的寄存器
DMA_ITConfig(DMA_CHx, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA_CHx, ENABLE);
// 根據(jù)端口選擇DMA監(jiān)聽
switch(port)
{
case UART_PORT1:
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
break;
case UART_PORT2:
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
break;
case UART_PORT3:
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
break;
case UART_PORT4:
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
break;
default:
break;
}
// 串口5 不支持DMA
switch(port)
{
case UART1:
case UART2:
case UART3:
case UART4:
// 開啟DMA 發(fā)送
USART_DMACmd(uartDef->port,USART_DMAReq_Tx,ENABLE);
USART_DMA_Config(uartDef->txChannel,
0,DMA_DIR_PeripheralDST,
(u32)&uartDef->port->DR,(u32)(uartDef->txBuffer));
// 開啟DMA 接收
USART_DMACmd(uartDef->port,USART_DMAReq_Rx,ENABLE);
USART_DMA_Config(uartDef->rxChannel,
uartDef->rxMaxLen,DMA_DIR_PeripheralSRC,
(u32)&uartDef->port->DR,(u32)(uartDef->rxBuffer));
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
break;
default:
break;
}
DMA 中斷處理(DMA1_IT_TC6 是指通道6的中斷標(biāo)志)
if( DMA_GetITStatus(DMA1_IT_TC6)==SET)
{
DMA_ClearITPendingBit(DMA1_IT_GL6);
DMA_Cmd(uartDef->rxChannel,DISABLE);
uartDef->rxLen = uartDef->rxMaxLen - DMA_GetCurrDataCounter(uartDef->rxChannel);
if (NULL != uartDef->callback)
{
uartDef->callback(UART_PORT2,EVENT_UART_READY_TO_READ,uartDef->customizePara);
}
DMA_SetCurrDataCounter(uartDef->rxChannel,uartDef->rxMaxLen);
DMA_Cmd(uartDef->rxChannel,ENABLE);
}
USART 中斷處理
if(USART_GetITStatus(uartDef->port, USART_IT_IDLE) != RESET)
{
res = uartDef->port->SR;
res = uartDef->port->DR;
DMA_Cmd(uartDef->rxChannel,DISABLE);
uartDef->rxLen = uartDef->rxMaxLen - DMA_GetCurrDataCounter(uartDef->rxChannel);
if (NULL != uartDef->callback)
{
uartDef->callback(port,EVENT_UART_READY_TO_READ,uartDef->customizePara);
}
DMA_SetCurrDataCounter(uartDef->rxChannel,uartDef->rxMaxLen);
DMA_Cmd(uartDef->rxChannel,ENABLE);
}
|
評分
-
查看全部評分
|