初级会员
- 积分
- 60
- 金钱
- 60
- 注册时间
- 2018-11-6
- 在线时间
- 14 小时
|
1金钱
本帖最后由 BG2DPB 于 2022-12-8 00:20 编辑
论坛的大佬们有没有碰到过这样的一个问题,就是在使用STM32F1的USART1和DMA传输数据时,只要STM32一接收到00数据时,STM32就默认为接收完成了,后面的数据就丢弃了,后面的数据就没办法接收了。我之前碰到过这个问题,是在调Modbus协议的时候,从传感器发过来的数据 只要是有00数据,这个通讯就中断了,后面的数据就接收不到了,一直卡在这里,导致后的传感器数据根本没办法解析。最近是在调上位机和STM32通讯过程中发现这个问题,上位机是Visual Studio编写的,只要是上位机发送00数据时,STM32解析就失败了,饶了一大圈还是回到了刚开始的哪个问题,STM32F1串口一接收到00数据就中断了。小弟没有头绪了(头大),还请各位论坛的大佬们给一点建议。
另外好像串口工作在空闲中断和DMA模式会出现这种情况,在接收中断的情况下好像没有出现这种情况?
usart2.c
//初始化函数
void uart2_init(unsigned long bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//USART2_TX GPIOA.2 = TX
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//USART2_RX GPIOA.3 = RX
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //复用开漏输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
//中断初始化
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
//串口2初始化
USART_InitStructure.USART_BaudRate = bound;
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_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure); //串口1初始化
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); //是能串口DMA接收
// USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
// USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//使能空闲中断
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(USART2->DR);//DMA外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&USART2_RX_BUF[0];//DMA接收端地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//设置DMA的传输方向,从外设到内存
DMA_InitStructure.DMA_BufferSize = USART2_REC_LEN;//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_Priority = DMA_Priority_Medium;//DMA1的Channel6
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel6,&DMA_InitStructure); //DMA1_Channel6 配置
USART_Cmd(USART2, ENABLE); //使能串口2
DMA_Cmd(DMA1_Channel6,DISABLE);
MYDMA_Enable();
}
void MYDMA_Enable(void)
{
DMA_Cmd(DMA1_Channel6,DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel6,10);//先默认设置成10长度
DMA_Cmd(DMA1_Channel6, ENABLE);
}
main.c
int main(void)
{
char Modbus_Buff[100];//接受的字符串数组
// int string_len;//获取字符串的长度
GPIO_Config();//GPIO初始化
uart_init(115200);
uart2_init(9600);
// TIM2_PWM_Init();
delay_ms(1000);
printf("Init_Succeed!\r\n");
while(1)
{
count_i++;
//该Modbus函数将串口移植到了USART2上面,所以串口1可以用来做调试使用
if(USART2_RX_BUF[0])
{
delay_ms(10);
strcpy(Modbus_Buff, USART2_RX_BUF);//复制字符串保存
memset(USART2_RX_BUF,0,10);//清空数组
MYDMA_Enable();//开始一次DMA传输
modbus(Modbus_Buff,10);
Demo_Deal(Receive_Buf);//尝试解析数据
}
// if(Receive_Flag == 1)//如果串口2获取到一帧数据
// {
// strcpy(Modbus_Buff, USART2_RX_BUF);//复制字符串保存
// string_len = strlen(Modbus_Buff);
// modbus(Modbus_Buff,string_len);
// Receive_Flag = 0;
// Demo_Deal(Receive_Buf);//把接收到的数据发送回去
// }
if(count_i<500) //0.2s
{
GPIO_ResetBits(GPIOC,GPIO_Pin_13); //上电点亮LED
// printf("A!\r\n");
}
else if((count_i>500)&&(count_i<1000))
{
GPIO_SetBits(GPIOC,GPIO_Pin_13); //上电点亮LED
// printf("B!\r\n");
}
else if(count_i>=1000)
{
count_i=0;
}
}
}
完整程序详见附件中的压缩包
|
|