小学生
最后登录1970-1-1
在线时间 小时
注册时间2020-4-25
|
我使用dma双缓冲,配合串口的空闲中断,接收遥控器的DBUS信号,可以进入空闲中断,但是将内存接收数组打印出来都是0,在仿真中可以看到串口数据寄存器中是有数据的,使用普通的RXNE中断可以正常接收,但是使用dma空闲中断
不管DMA开不开双缓存接收的内存数组中都是0
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,@Ref DMA_channel DMA_Channel_0~DMA_Channel_7
//par:外设地址
//mar:存储器地址
//direction:数据传输方向
//ndtr:数据传输量
//dmamode:dma模式
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u32 direction,u16 ndtr,u32 dmamode)
{
DMA_InitTypeDef DMA_InitStructure;
if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
}else
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
}
DMA_DeInit(DMA_Streamx);
while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = chx; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = direction;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = dmamode;// 使用普通模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
}
u8 USART4_DBUS_RX_BUF[18];
u8 USART4_DBUS_RX_BUF1[18];
void Uart4_DBUS_Init(u32 bound) //串口3
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOB时钟
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA1,ENABLE);
//串口3对应引脚复用映射
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4);
//UART4端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
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; //收发模式
USART_Init(UART4, &USART_InitStructure);
//Uart5 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
MYDMA_Config(DMA1_Stream2,DMA_Channel_4,(u32)&UART4->DR,
(u32)USART4_DBUS_RX_BUF,
DMA_DIR_PeripheralToMemory,
USART4_DBUS_LEN,
DMA_Mode_Circular); //最大一次接收256字节
DMA_DoubleBufferModeConfig(DMA1_Stream2,(uint32_t)USART4_DBUS_RX_BUF1,DMA_Memory_0);
DMA_DoubleBufferModeCmd(DMA1_Stream2,ENABLE);
USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE); //使能DMA接收
DMA_Cmd(DMA1_Stream2, ENABLE);
USART_ITConfig(UART4, USART_IT_IDLE,ENABLE); //使能串口4空闲中断
USART_Cmd(UART4, ENABLE); //使能串口4
}
u16 Remote[12];
void RemoteData(u8 *pData)
{
Remote[0] = (((int16_t)pData[1] << 8) | (int16_t)pData[0]) & 0x07FF;
Remote[1] = (((int16_t)pData[2] << 5) | ((int16_t)pData[1] >> 3)) & 0x07FF;
}
u16 s[2]={0,0};
extern int Motor[2];
extern float K;
u8 UART4_RX_LEN=0;
int i;
void UART4_IRQHandler(void) //串口3 GPS中断服务程序
{
u8 res;
if(USART_GetITStatus(UART4,USART_IT_IDLE) != RESET)
{
USART_ClearITPendingBit(UART4 ,USART_IT_IDLE); //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
res = UART4->SR;
res = UART4->DR; //清除中断标志位
// num = USART_ReceiveData(UART4);//读取DR寄存器,清除中断标志位
DMA_Cmd(DMA1_Stream2, DISABLE);
DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF2 | DMA_IT_TEIF2); // Clear Transfer Complete flag
DMA_ClearFlag(DMA1_Stream2,DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2);//清除DMA1_Steam1传输完成标志
if(DMA_GetCurrentMemoryTarget(DMA1_Stream2) == 0)
{
RemoteData(USART4_DBUS_RX_BUF);
Motor[0]=(Remote[1]+Remote[0]-2048)*K;
Motor[1]=(Remote[1]-Remote[0])*K;
}
else if(DMA_GetCurrentMemoryTarget(DMA1_Stream2) == 1)
{
RemoteData(USART4_DBUS_RX_BUF1);
Motor[0]=(Remote[1]+Remote[0]-2048)*K;
Motor[1]=(Remote[1]-Remote[0])*K;
}
//
for(i=0;i<18;i++)
{
printf("%d,",USART4_DBUS_RX_BUF);
}
printf("\r\n");
for(i=0;i<18;i++)
{
printf("%d,",USART4_DBUS_RX_BUF1);
}
printf("\r\n");
DMA_SetCurrDataCounter(DMA1_Stream2, USART4_DBUS_LEN);
DMA_Cmd(DMA1_Stream2, ENABLE);
}
USART_ClearITPendingBit(UART4,USART_IT_IDLE); // 清除标志位
Motor_Control(Motor);
}
|
|