1.DMA簡介
直接存儲(chǔ)器存取(DMA)用來提供在外設(shè)和存儲(chǔ)器之間或者存儲(chǔ)器和存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。無須CPU干預(yù),數(shù)據(jù)可以通過DMA快速地移動(dòng),這就節(jié)省了CPU的資源來做其他操作。
STM32F10x中有兩個(gè)DMA控制器(DMA1有7個(gè)通道,DMA2有5個(gè)通道)每個(gè)通道專門用來管理來自于一個(gè)或多個(gè)外設(shè)對(duì)存儲(chǔ)器訪問的請(qǐng)求。還有一個(gè)仲裁器來協(xié)調(diào)各個(gè)DMA請(qǐng)求的優(yōu)先權(quán)。
DMA1請(qǐng)求映像
??USART1_TX – DMA1_Chnanel4
??USART1_RC – DMA1_Channel5
??利用DMA功能完成串口數(shù)據(jù)處理,無需CPU干預(yù),減少CPU占用。
2.程序設(shè)計(jì)
?1.DMA1_CH4配置
/******DMA配合串口1發(fā)送數(shù)據(jù)************
**形參:u32 cpar -- 外設(shè)地址
**
**例:DMA_CH4_Init(&USART1->DR,buff)
**外設(shè)地址:USART1->DR的地址
** buff的地址
**************************************/
void DMA_CH4_Init(u32 cpar)
{
RCC->AHBENR|=1<<0;//dma1時(shí)鐘使能
DMA1_Channel4->CCR&=~(1<<14);//非存儲(chǔ)器到存儲(chǔ)器模式
DMA1_Channel4->CCR|=0x3<<12;//設(shè)置CH4優(yōu)先級(jí)為最高
DMA1_Channel4->CCR&=~(0x3<<10);//存儲(chǔ)器數(shù)據(jù)寬度8位
DMA1_Channel4->CCR&=~(0x3<<8);//外設(shè)數(shù)據(jù)寬度8位
DMA1_Channel4->CCR|=1<<7;//存儲(chǔ)器地址增量
DMA1_Channel4->CCR&=~(1<<6);//外設(shè)地址不增量
DMA1_Channel4->CCR&=~(1<<5);//不執(zhí)行循環(huán)操作
DMA1_Channel4->CCR|=1<<4;//從存儲(chǔ)器讀
DMA1_Channel4->CPAR=cpar;//外設(shè)地址
}
/**********開啟DMA1_CH4數(shù)據(jù)傳輸*************
***
***形參:u16 data_len -- DMA要傳輸數(shù)目
***********************************************/
void DMA_CH4_Start(u8 *buff,u16 data_len)
{
DMA1_Channel4->CMAR=(u32)buff;//存儲(chǔ)器地址
DMA1_Channel4->CCR&=~(1<<0);//關(guān)閉通道傳輸
DMA1_Channel4->CNDTR=data_len;//設(shè)置傳輸數(shù)量
DMA1_Channel4->CCR|=1<<0;//開啟通道傳輸
}
??2.DMA1_CH5配置
/******DMA配合串口1接收數(shù)據(jù)************
**形參:u32 cpar -- 外設(shè)地址
** u32 cmar -- 存儲(chǔ)器地址
**
**例:DMA_CH5_Init(&USART1->DR,buff)
**外設(shè)地址:USART1->DR的地址
** buff的地址
**************************************/
void DMA_CH5_Init(u32 cpar,u32 cmar)
{
RCC->AHBENR|=1<<0;//dma1時(shí)鐘使能
DMA1_Channel5->CCR&=~(1<<14);//非存儲(chǔ)器到存儲(chǔ)器模式
DMA1_Channel5->CCR|=0x3<<12;//設(shè)置CH4優(yōu)先級(jí)為最高
DMA1_Channel5->CCR&=~(0x3<<10);//存儲(chǔ)器數(shù)據(jù)寬度8位
DMA1_Channel5->CCR&=~(0x3<<8);//外設(shè)數(shù)據(jù)寬度8位
DMA1_Channel5->CCR|=1<<7;//存儲(chǔ)器地址增量
DMA1_Channel5->CCR&=~(1<<6);//外設(shè)地址不增量
DMA1_Channel5->CCR&=~(1<<5);//執(zhí)行循環(huán)操作
DMA1_Channel5->CCR&=~(1<<4);//從外設(shè)讀
DMA1_Channel5->CPAR=cpar;//外設(shè)地址
DMA1_Channel5->CMAR=cmar;//存儲(chǔ)器地址
DMA1_Channel5->CCR&=~(1<<0);//關(guān)閉通道傳輸
DMA1_Channel5->CNDTR=1024;//設(shè)置傳輸數(shù)量
DMA1_Channel5->CCR|=1<<0;//開啟通道傳輸
}
??3.USART1配置
/********************串口初始化函數(shù)封裝*********************
****硬件接口:USART1_TX -- PA9(發(fā)送)
** USART1-RX --PA10(接收)
** USART2_TX -- PA2(發(fā)送)
** USART2-RX --PA3(接收)
** USART3_TX -- PB10(發(fā)送)
** USART3_RX -- PB11(接收)
形參:USART_TypeDef *USARTx -- 要配置的哪個(gè)串口
** u32 baud --波特率
** u32 sysclk --時(shí)鐘頻率(USART1 --72MHZ ,USAT2USART3 --36MHZ)
**
***********************************************************/
void Usartx_Init(USART_TypeDef *USARTx,u32 baud,u32 sysclk)
{
if(USART1 == USARTx)
{
/*1.開時(shí)鐘*/
RCC->APB2ENR|=1<<2;//PA時(shí)鐘
RCC->APB2ENR|=1<<14;//串口時(shí)鐘
RCC->APB2RSTR|=1<<14;//串口復(fù)位
RCC->APB2RSTR&=~(1<<14);//取消復(fù)位
/*2.配置GPIO口*/
GPIOA->CRH&=0xFFFFF00F;
GPIOA->CRH|=0x000008B0;//上下拉輸入,復(fù)用推挽輸出
USART1->CR3|=1<<7;//DMA發(fā)送
USART1->CR3|=1<<6;//DMA接收
USART1->CR1|=1<<4;//IDLE(空閑幀中斷)
STM32_NVIC_SetPriority(USART1_IRQn,0,1);//設(shè)置優(yōu)先級(jí)
}
else if(USART2 == USARTx)
{
/*1.開時(shí)鐘*/
RCC->APB2ENR|=1<<2;//PA時(shí)鐘
RCC->APB1ENR|=1<<17;//USART2時(shí)鐘
RCC->APB1RSTR|=1<<17;//開復(fù)位時(shí)鐘
RCC->APB1RSTR&=~(1<<17);//取消復(fù)位
/*2.配置GPIO口*/
GPIOA->CRL&=0xFFFF00FF;//清除原來寄存器中的值
GPIOA->CRL|=0x00008B00;
#ifdef USART2_IRQ
USART2->CR1|=1<<5;//串口2接收中斷
STM32_NVIC_SetPriority(USART2_IRQn,1,2);//設(shè)置優(yōu)先級(jí)
#endif
}
else if(USART3 == USARTx)
{
/*1.開時(shí)鐘*/
RCC->APB2ENR|=1<<3;//PB時(shí)鐘
RCC->APB1ENR|=1<<18;//USART3時(shí)鐘
RCC->APB1RSTR|=1<<18;//開復(fù)位時(shí)鐘
RCC->APB1RSTR&=~(1<<18);//取消復(fù)位
/*2.配置GPIO口*/
GPIOB->CRH&=0xFFFF00FF;
GPIOB->CRH|=0x00008B00;
#ifdef USART3_IRQ
USART3->CR1|=1<<5;//開啟接收中斷
STM32_NVIC_SetPriority(USART3_IRQn,0,0);//設(shè)置優(yōu)先級(jí)
#endif
}
else return;
/*3.配置串口核心寄存器*/
USARTx->BRR=sysclk*1000000/baud;//設(shè)置波特率
USARTx->CR1|=1<<2;//接收使能
USARTx->CR1|=1<<3;//發(fā)送使能
USARTx->CR1|=1<<13;//使能串口3
#ifdef DMA_USART1_SEND //利用DMA完成數(shù)據(jù)收發(fā)
DMA_CH5_Init((u32 )&USART1->DR,(u32 )usart1_rx_buff);//DMA配合串口1接收數(shù)據(jù)
DMA_CH4_Init((u32 )&USART1->DR);
#endif
}
4.串口1中斷,DMA數(shù)據(jù)接收數(shù)據(jù)
u8 usart1_rx_buff[1024];//串口1接收數(shù)據(jù)緩沖區(qū)
u16 usart1_cnt=0;//保存數(shù)組下班
u8 usart1_flag;//接收完成標(biāo)志符
void USART1_IRQHandler(void)
{
U8 C;
//清除標(biāo)志:先讀USART_SR,再讀USART_DR
if(USART1->SR&1<<4)//空閑幀
{
C=USART1->DR;
C=c;
// USART1->DR=c;
Usart1_Receive_Data();//接收數(shù)據(jù)處理函數(shù)
}
USART1->SR=0;//清除標(biāo)志位
}
/*************************串口接收數(shù)據(jù)函數(shù)********************/
void Usart1_Receive_Data(void)
{
DMA1_Channel5->CCR&=~(1<<0);//關(guān)閉通道傳輸
usart1_cnt=1024-DMA1_Channel5->CNDTR;//獲取接收到是字符長度
if(usart1_cnt>=1024)usart1_cnt=0;
DMA1->IFCR|=1<<17;//清除標(biāo)志位
DMA1_Channel5->CNDTR=1024;//從新賦值
DMA1_Channel5->CCR|=1<<0;//開啟通道傳輸
usart1_flag=1;
}
??5.串口數(shù)據(jù)發(fā)送
/****************串口發(fā)送字符串*****************************/
void Usart1_SendStr(u8 *str)
{
#ifdef DMA_USART1_SEND
DMA_CH4_Start(str,strlen((char *)str));
#else
while(*str!='?')
{
USART1->DR=*str++;
while(!(USART1->SR&1<<7));
}
#endif
}
6.硬件初始化,DMA配合串口調(diào)試
int main()
{
u8 key;
Beep_Init();//蜂鳴器初始化
Led_Init();//LED初始化
Key_Init();//按鍵初始化
Usartx_Init(USART1,115200,72);
while(1)
{
key=Key_Scan();
if(key)
{
Usart1_SendStr((u8 *)"DMA1配合串口收發(fā)數(shù)據(jù)不定長測試234556789rn");
}
if(usart1_flag)
{
usart1_rx_buff[usart1_cnt]='?';
printf("%srn",usart1_rx_buff);
usart1_flag=0;
}
}
}
7.運(yùn)行效果
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7484瀏覽量
163762 -
STM32F10x
+關(guān)注
關(guān)注
1文章
81瀏覽量
20681 -
dma
+關(guān)注
關(guān)注
3文章
560瀏覽量
100544
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論