串口+DMA初始化配置
USART_Configuration(9600,ENABLE);//串口数据
DMA1_Channel5_Configuration();
Usart1:
void USART_Configuration(u32 baudrate,FunctionalState NewState)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO; //声明一个结构体变量
NVIC_InitTypeDef NVIC_InitStructure;
//时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//nvic中断优先级配置
/* ?? USART ???? */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化NVIC寄存器
//USART1_TX PA.9
//USART1_RX PA.10
GPIO.GPIO_Pin = GPIO_Pin_10; //选择PX.3
GPIO.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
GPIO_Init(GPIOA,&GPIO); //初始化GPIOA寄存器
GPIO.GPIO_Pin = GPIO_Pin_9;
GPIO.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
GPIO.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为推挽复用输出
GPIO_Init(GPIOA,&GPIO); //初始化GPIOA寄存器
//usart
USART_DeInit(USART1);
USART_InitStructure.USART_BaudRate = baudrate;
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_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
// USART_ITConfig(USART1, USART_IT_RXNE,NewState);//开接收中断
USART_Cmd(USART1, NewState);
}
DMA:
//channel5 接收
//channel4 发送
#define USART1_DR_Base (u32)(0x40013804)
void DMA1_Channel5_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQChannel; //DMA中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel5 (triggered by USART1 Rx event) Config */
DMA_DeInit(DMA1_Channel5); // 将DMA1_Channel5寄存器重设为初始值 ;
DMA_InitStructure.DMA_PeripheralBaseAddr =USART1_DR_Base ; //用来定义DMA外设的基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_Buffer_Rx; //用来定义DMA内存的基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向
DMA_InitStructure.DMA_BufferSize = USART1_Buffer_Rx_Size; //传输数据的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //DMA外设地址
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //DMA内存地址+1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//传输的字节宽度HalfWord
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //字节宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //传输模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //使能内存到内存的传输
DMA_Init(DMA1_Channel5,&DMA_InitStructure); //初始化
DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA
/* DMA1 Channel4 (triggered by USART1 Tx event) Config */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQChannel; //DMA中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_DeInit(DMA1_Channel4);
// DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base; // 外设地址,串口1
// DMA_InitStructure.DMA_MemoryBaseAddr =(u32)USART1_Buffer_Rx;// 发送内存地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//传输的字节宽度HalfWord
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //字节宽度
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;// 外设为传送数据目的地,即发送数据
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //传输模式
DMA_Init(DMA1_Channel4, &DMA_InitStructure);//初始化
DMA_Cmd(DMA1_Channel4,ENABLE); while(!USART_GetFlagStatus(USART1, USART_FLAG_TC)); //使能DMA
// DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE); // 接收传输完成中断
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); // 发送传输完成中断
// USART_ITConfig(USART1, USART_IT_TC, ENABLE); // 使能串口发送完成中断
USART_DMACmd(USART1,USART_DMAReq_Tx|USART_DMAReq_Rx,ENABLE);
}
DMA接收通道优先级似乎应高于发送通道,否则会出现接收问题(待验证)
DMA通道的使用
查看DMA请求映像可知USART1对应
//channel5 接收
//channel4 发送
USART1_DR_Base
这是外设USART1的数据寄存器(USART_DR) 地址偏移:0x04
查看存储器映像得外设起始地址
相加即为USART1_DR_Base
开启一次DMA传输
1.得到DMA对应数字。判断等待DMA传输和串口传输完成
2.
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
3.清除传输完成标志
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx,u16 DMA1_MEM_LEN)
{
u8 num=255;
u32 tc=0;
switch (*(u32*)&DMA_CHx)
{
case DMA1_Channel1_BASE:
num=11;
break;
case DMA1_Channel2_BASE:
num=12;
break;
case DMA1_Channel3_BASE:
num=13;
break;
case DMA1_Channel4_BASE:
num=14;
break;
case DMA1_Channel5_BASE:
num=15;
break;
case DMA1_Channel6_BASE:
num=16;
break;
case DMA1_Channel7_BASE:
num=17;
break;
case DMA2_Channel1_BASE:
num=21;
break;
case DMA2_Channel2_BASE:
num=22;
break;
case DMA2_Channel3_BASE:
num=23;
break;
case DMA2_Channel4_BASE:
num=24;
break;
case DMA2_Channel5_BASE:
num=25;
break;
default:
break;
}
if(num>10&&num<20)
tc|=1<<((num%10-1)*4+1);
else if(num>20)
{
tc=0x10000000;
tc|=1<<((num%10-1)*4+1);
}
// while(!DMA_GetFlagStatus(tc)); //判断传输是否完成与dma中断互斥。不能同时用。
switch(num%10)
{
case 2:
case 3:
while(!USART_GetFlagStatus(USART3, USART_FLAG_TC));
break;//判断发送完成
case 4:
case 5:
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
break;
case 6:
case 7:
while(!USART_GetFlagStatus(USART2, USART_FLAG_TC));
break;
default:
break;
}
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
DMA_ClearFlag(DMA_FLAG_TC); //清除传输完成标志
DMA_CHx->IFCR|=1<<13;
tc= ((u32)0x00000000);
if(num>10&&num<20)
{
tc|=(0xf)<<(num%10-1)*4;
DMA1->IFCR |=tc;
}
else if(num>20)
{
tc|=(0xf)<<(num%10-1)*4;
DMA2->IFCR |=tc;
}
// switch (*(u32*)&DMA_CHx)//标志全部清除
// {
// case DMA1_Channel1_BASE:num=11;DMA1->IFCR |= ((u32)0x0000000F);break;
// case DMA1_Channel2_BASE:num=12;
// DMA1->IFCR |= ((u32)0x000000F0);
// break;
// case DMA1_Channel3_BASE:num=13;
// DMA1->IFCR |= DMA1_Channel3_IT_Mask;
// break;
// case DMA1_Channel4_BASE:num=14;
// DMA1->IFCR |= DMA1_Channel4_IT_Mask;
// break;
// case DMA1_Channel5_BASE:num=15;
// DMA1->IFCR |= DMA1_Channel5_IT_Mask;
// break;
// case DMA1_Channel6_BASE:num=16;
// DMA1->IFCR |= DMA1_Channel6_IT_Mask;
// break;
// case DMA1_Channel7_BASE:num=17;
// DMA1->IFCR |= DMA1_Channel7_IT_Mask;
// break;
// case DMA2_Channel1_BASE:num=21;
// DMA2->IFCR |= DMA2_Channel1_IT_Mask;
// break;
// case DMA2_Channel2_BASE:num=22;
// DMA2->IFCR |= DMA2_Channel2_IT_Mask;
// break;
// case DMA2_Channel3_BASE:num=23;
// DMA2->IFCR |= DMA2_Channel3_IT_Mask;
// break;
// case DMA2_Channel4_BASE:num=24;
// DMA2->IFCR |= DMA2_Channel4_IT_Mask;
// break;
// case DMA2_Channel5_BASE:num=25;
// DMA2->IFCR |= DMA2_Channel5_IT_Mask;
// break;
// default:
// break;
// }
}
it.c文件
中断处理【清理完成标志。标记自己的CurrDataCounter_End】
extern u16 CurrDataCounter_End;
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC4)) // 通道4发送传输完成中断 ;
{
CurrDataCounter_End =1;
DMA_ClearITPendingBit(DMA1_IT_GL4); // 清除DMA通道4中断全局标志位 ;
}
}
void DMA1_Channel5_IRQHandler(void)//接收
{
// if(DMA_GetITStatus(DMA1_IT_TC5)) // 通道5传输完成中断 ;
// {
// /* Get Current Data Counter value after complete transfer */
// // CurrDataCounter_End = DMA_GetCurrDataCounter(DMA1_Channel5); // 返回当前DMA通道5剩余的待传输数据数目 ;
// /* Clear DMA Channel6 Half Transfer, Transfer Complete and Global interrupt pending bits */
// DMA_ClearITPendingBit(DMA1_IT_GL5); // 清除DMA通道5中断全局标志位 ;
// }
}