標(biāo)題: STM32F030-UART1_DMA使用提示 [打印本頁(yè)]
作者: IdeaMing 時(shí)間: 2018-6-27 18:45
標(biāo)題: STM32F030-UART1_DMA使用提示
STM32F030-UART1_DMA使用提示前言: 今天把STM32F030C8T6的串口DMA學(xué)習(xí)了一下,為了加快各位研發(fā)人員的開(kāi)發(fā)進(jìn)度,避免浪費(fèi)大量的時(shí)間在硬件平臺(tái)上,寫(xiě)出個(gè)人代碼調(diào)試的經(jīng)驗(yàn)。個(gè)人水平有限,如有錯(cuò)誤,還請(qǐng)指正mr.li.ming@qq.com。
提示:使用的內(nèi)部RC時(shí)鐘,最大速度48MHz;使用USART1-PA9/PA10.
第一步:初始化端口/*******************************************************************************
*@brief 串口1端口初始化
*@param None
* @retvalNone
****************************************************************Author:Liming**/
void USART1_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_Initstructure;
RCC_AHBPeriphClockCmd(USART1_GPIO_CLK,ENABLE);
/*Connect pin to Periph */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); // 注意這里是GPIO_PinSource9
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_Initstructure.GPIO_Pin=USART1_TX_PIN;
GPIO_Initstructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_Initstructure.GPIO_OType=GPIO_OType_PP; // 推挽輸出
GPIO_Initstructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(USART1_GPIO_PORT,&GPIO_Initstructure);
GPIO_Initstructure.GPIO_Pin = USART1_RX_PIN; // 浮空輸入
GPIO_Init(USART1_GPIO_PORT,&GPIO_Initstructure);
}
第二步:初始化UART1/*******************************************************************************
* @brief 串口1初始化
* @param None
* @retval None
****************************************************************Author:Liming**/
void USART1_Init(uint32_t BaudRate)
{
USART_InitTypeDef USART_Initstructure;
RCC_APB2PeriphClockCmd(USART1_CLK,ENABLE);
USART1_GPIO_Init(); // 調(diào)用了上面的端口初始化,故主函數(shù)里調(diào)用此函數(shù)即可。
USART_Initstructure.USART_BaudRate = BaudRate;
USART_Initstructure.USART_Parity =USART_Parity_No;
USART_Initstructure.USART_WordLength =USART_WordLength_8b;
USART_Initstructure.USART_StopBits =USART_StopBits_1;
USART_Initstructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_Initstructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_Initstructure);
USART_ClearFlag(USART1,USART_FLAG_TC);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
USART_Cmd(USART1,ENABLE); // 使能串口
}
第三步:DMA1中斷配置/*******************************************************************************
* @brief DMA1中斷配置
* @param None
* @retval None
****************************************************************Author:Liming**/
void DMA1_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
注意事項(xiàng):1. USART1發(fā)送數(shù)據(jù)使用的是DMA1的第二通道。查表可知,為什么還有第四通道呢,那是給USART1端口重映射了之后使用的。
第四步:DMA1配置/*******************************************************************************
*@brief DMA1配置
*@param None
*@retval None
****************************************************************Author:Liming**/
void DMA1_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_InitStructure.DMA_BufferSize = 12; // 緩存大小
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 內(nèi)存到內(nèi)存關(guān)閉
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 普通模式
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 內(nèi)存到外設(shè)
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道優(yōu)先級(jí)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 內(nèi)存地址遞增
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)&USART1->TDR; // 外設(shè)地址
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 外設(shè)地址不變
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 內(nèi)存數(shù)據(jù)長(zhǎng)度
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)UART1_TXBUFFER; // 定義內(nèi)存基地址
DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Byte;//外設(shè)數(shù)據(jù)長(zhǎng)度
DMA_Init(DMA1_Channel2,&DMA_InitStructure);
DMA_ClearITPendingBit(DMA1_IT_TC2); // 清除一次DMA中斷標(biāo)志
DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);// 使能DMA傳輸完成中斷
DMA1_NVIC_Init(); // 調(diào)用了上面的中斷配置,故主函數(shù)里調(diào)用此函數(shù)即可
DMA_Cmd(DMA1_Channel2,ENABLE);
}
注意事項(xiàng):1. 緩存大。壕褪悄阋淮我l(fā)送多長(zhǎng)的數(shù)據(jù)。2. DMA方向:因?yàn)槭谴诎l(fā)送數(shù)據(jù),所以是從內(nèi)存到外設(shè),USART1對(duì)于單片機(jī)來(lái)講是個(gè)外設(shè)。定義的發(fā)送數(shù)組是內(nèi)存。3. 內(nèi)存地址遞增:其實(shí)不難理解,從發(fā)送數(shù)組的UART1_TXBUFFER[0]- UART1_TXBUFFER[n]肯定是遞增的。4. 外設(shè)地址不遞增:所有的數(shù)據(jù)都是通過(guò)串口發(fā)送寄存器發(fā)出去,所以外設(shè)地址不變。5. 內(nèi)存/外設(shè)數(shù)據(jù)長(zhǎng)度:串口發(fā)送的數(shù)據(jù)都是字節(jié)為單位,所以長(zhǎng)度是Byte6. DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);注意這一句不要寫(xiě)錯(cuò)。
第五步:DMA1的中斷處理函數(shù)/**
*@brief DMA1_Channel1中斷服務(wù)函數(shù)
*@param 無(wú)
*@retval 無(wú)
*/
void DMA1_Channel2_3_IRQHandler(void)
{
/*判斷DMA傳輸完成中斷*/
if(DMA_GetITStatus(DMA1_IT_TC2)!= RESET)
{
UART1_STATE = 2;// send over
}
/*清除DMA中斷標(biāo)志位*/
DMA_ClearITPendingBit(DMA1_IT_TC2);
}
這里使用了一個(gè)變量UART1_STATE作為標(biāo)志位
第六步:使用DMA1發(fā)送串口數(shù)據(jù)
USART1_Init(115200);
DMA1_Init();
while(1)
{
if(UART1_STATE==2)
{
UART1_STATE = 1;
DMA_Cmd(DMA1_Channel2,DISABLE); // 發(fā)送完成先關(guān)掉DMA通道
DMA_SetCurrDataCounter(DMA1_Channel2,12); // 設(shè)置需要發(fā)送的長(zhǎng)度
DMA_Cmd(DMA1_Channel2,ENABLE); // 再打開(kāi)DMA通道
}
GPIO_SetBits(GPIOA,GPIO_Pin_4);Delay(500);
GPIO_SetBits(GPIOA,GPIO_Pin_3);Delay(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);Delay(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_3);Delay(500);
}
注意事項(xiàng):1. 一定要注意,DMA的傳輸有個(gè)長(zhǎng)度計(jì)數(shù)器,DMA傳輸完成后,計(jì)數(shù)器里的值就變成了0;數(shù)據(jù)是不傳了,但是通道并沒(méi)有關(guān)閉。所以想要再次傳輸就需要修改這個(gè)長(zhǎng)度計(jì)數(shù)器的值,但是這個(gè)值的修改必須要關(guān)閉通道后修改。所以就有了上面的步驟,關(guān)閉通道—修改計(jì)數(shù)值—打開(kāi)通道
希望對(duì)各位看官有所幫助,并能觸類(lèi)旁通,對(duì)于外設(shè)到內(nèi)存啊,內(nèi)存到內(nèi)存啊,ADC與DMA啊,SPI與DMA都能輕松的應(yīng)用。
作者: ababzx2199 時(shí)間: 2018-8-21 14:49
好資料,51黑有你更精彩!!!
作者: IdeaMing 時(shí)間: 2018-8-23 16:46
還請(qǐng)大神勿噴!如果覺(jué)得哪里不對(duì)可以提出來(lái),我做改正。
作者: askloser 時(shí)間: 2018-12-14 22:22
學(xué)習(xí)了
作者: MR.Xuan 時(shí)間: 2019-10-16 10:27
學(xué)習(xí)了
作者: dbwu8280 時(shí)間: 2019-10-16 13:40
學(xué)習(xí)了,51黑不錯(cuò)!
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |