在液晶屏上显示一副彩 {MOD}图片(320*240)约为150K字节,图片数据是从串口接收,然后存储到外部FLASH(W25Q64)中,查了一些资料,打算使用串口+DMA+双缓冲的方式接收处理数据,串口波特率为57600,串口使用空闲中断的方式来判断DMA接收完成。 DMA定义了两个数据,大小为4096。串口一直在接收数据,应该是接收到4096字节的时候,进入DMA中断,然后DMA中断切换为另一个缓冲接收数据,当接收到最后的2048个字节后进入串口空闲中断,表示图片数据已经接收完全了。
但是现在遇到一个问题,还没接收到4096字节的时候,串口就进入到了空闲中断,请问这是什么问题啊?我的程序如下:
void uart_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//配置时钟
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE) ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE) ;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE) ;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE) ;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); // JTAG Disable,SWD Enable
USART_DeInit(USART2); //复位串口2
//USART1_TX GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
//USART1_RX GPIOA.3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA.3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3
//485_Enable GPIOA.15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //PA.15
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
RS485_Pin=0; //开机默认接收
////////////////////////////////////////////////////////////////////////////////
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//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(USART2, &USART_InitStructure); //初始化串口2
//中断配置
USART_ITConfig(USART2,USART_IT_IDLE,ENABLE); //开启接收空闲中断
USART_Cmd(USART2, ENABLE); //使能串口2
}
/*********************** 配置RX_DMA ************************/
void USART2_DMA_RX(void)
{
//串口接收DMA配置
//DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//启动DMA时钟
USART_DMACmd(USART2,USART_DMAReq_Rx,DISABLE);
DMA_DeInit(DMA1_Channel6); // 串口2 接收 DMA传输通道是通道6
DMA_InitStructure.DMA_PeripheralBaseAddr = ((u32)(&(USART2->DR))); //DMA外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART2_DMA_RX_Buf1;//DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向:从外设读取发送到内存
DMA_InitStructure.DMA_BufferSize = USART2_RX_Buf_Len; //DMA通道的DMA缓存的大小
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 = DMA_Mode_Normal;//工作在正常缓存模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//工作在循环模式
//DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMA通道x拥有最高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel6 , &DMA_InitStructure); //初始化DMA的通道
DMA_ClearFlag(DMA1_FLAG_TC6); //清除DMA接收完成标志
DMA_Cmd(DMA1_Channel6 , ENABLE) ;
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);//使能DMA传输完成中断
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); //使能串口2 DMA接收
//Free_Buf_No=BUF_NO2; //因为 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART2_DMA_RX_Buf1;
Free_Buf_No=BUF_NO1;
Buf_Ok=0; //此时没有数据准备完成 当然FALSE
//配置NVIC 配置串口DMA的中断优先级
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;
NVIC_Init(&NVIC_InitStructure);
}
/*************** 串口2中断服务程序 *********************/
void USART2_IRQHandler(void)
{
u32 temp = 0;
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //判断是否真的空闲帧来了
{
//USART_ClearFlag(USART2,USART_IT_IDLE);
temp = USART2->SR; //先读SR,然后读DR才能清除
temp = USART2->DR; //清USART_IT_IDLE标志
DMA_Cmd(DMA1_Channel6,DISABLE); //关闭DMA接收,防止其间还有数据过来
temp = USART2_RX_Buf_Len - DMA_GetCurrDataCounter(DMA1_Channel6); //计算接收的字节数
//Usart2_RX_Cou = temp; //保存接收到的字节数,main中处理后要清零
Buf_Ok = 1; //串口2一个数据包接收完成,标志置一,main中处理后要清零
DMA_SetCurrDataCounter(DMA1_Channel6,USART2_RX_Buf_Len);//设置传输数据长度,重装填,并让接收地址偏址从0开始
DMA_Cmd(DMA1_Channel6,ENABLE); //打开DMA接收
}
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, ENABLE);
}
//关闭一次DMA传输
void MYDMA_Disable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE);
}
void DMA1_Channel6_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC6)) //通道6传输完成中断TC 还有传输 过半中断HT 错误中断TE 全局中断GL
{
MYDMA_Disable(DMA1_Channel6);
//DataCounter = DMA_GetCurrDataCounter(DMA1_Channel6);//获取剩余长度,一般都为0,调试用
DMA_ClearITPendingBit(DMA1_IT_GL6); //清除全部中断标志
//DMA_InitStructure.DMA_BufferSize = (u16)200;
DMA_InitStructure.DMA_BufferSize = (u16)USART2_RX_Buf_Len;
//转换可操作BUF
if(Free_Buf_No==BUF_NO1) //如果BUF1空闲,将DMA接收数据赋值给BUF1
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART2_DMA_RX_Buf1;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
Free_Buf_No=BUF_NO2;
}
else //如果BUF2空闲,将DMA接收数据赋值给BUF2
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART2_DMA_RX_Buf2;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
Free_Buf_No=BUF_NO1;
}
Buf_Ok=1; //有准备好的数据了
MYDMA_Enable(DMA1_Channel6);
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
应该是电脑上的串口调试助手发送数据的时间不稳定,所以造成这样的情况。
一周热门 更多>