OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3298|回复: 4

stm32串口空闲中断在收到'0'、'P'字符时错误触发

[复制链接]

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
发表于 2017-11-25 21:31:06 | 显示全部楼层 |阅读模式
14金钱
问题描述:
    最近在做一个关于串口读压力模块压力值的项目,用到的压力模块的基本工作原理为,通过串口向压力模块发送读压力指令"1:R:MRMD:0:0"(字符串),压力模块会返回压力值字符串"1:F:MRMD:101.00:KPA"(非定长字符串),收到压力值字符串后需要对其进行分割,以提取标识位'F'、压力值'101.00',以及压力单位'KPA'。
    我做该项目的思路是通过DMA传输的方式将串口接收到的压力字符串从串口数据寄存器传输到内存,通过串口的总线空闲中断(IDLE)判断压力值字符串是否接收完成,若接收完成触发中断程序,在中断程序中对字符串中进行分割并提取具有关键值的子串。
    在调试程序的过程中,字符串的发送和接收都正常,但是总线空闲中断却不能正确地相应,出现了只有接收到'0'、'P'等ASCII码后四位为'0000'的字符才触发中断的情况。以前文中压力值("1:F:MRMD:101.00:KPA")为例,触发中断时只接收到"1:F:MRMD:10",这就导致了压力读取错误。若接收的压力字符串中没有类似'0'、'P'等字符串则始终不会产生中断。
    刚刚学习STM32的使用,困惑了好长时间,各位前辈若能有所指点,非常感激,下面就是我的程序。
主函数:
void Delay(__IO u32 nCount)     /*自定义的延时函数*/
{
     for(;nCount!=0;nCount--);
}
void USART_SendChar(USART_TypeDef* USARTx,uint8_t data)     /*自定义的串口发送数据函数*/
{
     USART_SendData(USARTx,data);
     while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
int main(void)
{
     char *str1;
     int i=0;
     USART1_Config();     /*串口初始化*/
     USART1_DMA_Config();     /*DMA初始化*/
     NVIC_Configuration();     /*中断优先级配置*/
     while(1)
     {
          str1="1:R:MRMD:0:0\n";     /*读压力指令*/
          USART_ClearFlag(USART1,USART_FLAG_TC);
          for(i=0;str1[i]!='\0';i++)     /*发送读压力指令*/
          {
               USART_SendChar(USART1,str1[i]);
          }
          USART_SendChar(USART1,0x0D);
          USART_SendChar(USART1,0x0A);     /*压力模块规定读压力指令以0D、0A结束*/
          Delay(500000);
          if(*temp1=='F')
          break;
     }
     while(1)
     {

     }
     pressure=atof(temp2);
}
串口及DMA配置:
#include "bsp_usart1.h"
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#define USART1_DR_Base 0x40013804
char PRESSURE[PRESSURE_LENGTH];    /*压力字符串在内存的缓冲区,其长度为512*/

void USART1_Config(void)
{
     GPIO_InitTypeDef GPIO_InitStructure;
     USART_InitTypeDef USART_InitStructure;

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
     GPIO_Init(GPIOA,&GPIO_InitStructure);

     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA,&GPIO_InitStructure);

     USART_InitStructure.USART_BaudRate=9600;
     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(USART1,&USART_InitStructure);
     USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
     USART_Cmd(USART1,ENABLE);
     USART_ClearFlag(USART1,USART_FLAG_TC);
}
void USART1_DMA_Config(void)
{
     DMA_InitTypeDef DMA_InitStructure;
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
     DMA_DeInit(DMA1_Channel5);
     DMA_InitStructure.DMA_PeripheralBaseAddr=USART1_DR_Base;
     DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&PRESSURE;
     DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
     DMA_InitStructure.DMA_BufferSize =PRESSURE_LENGTH;    /*传输数量为512*/
     DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
     DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
     DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
     DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
     DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;
     DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
     DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
     DMA_Init(DMA1_Channel5,&DMA_InitStructure);
     USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
     DMA_Cmd(DMA1_Channel5,ENABLE);
}
中断程序:
void USART1_IRQHandler(void)
{
     uint16_t i;
     uint8_t Clear=Clear;
  
     if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)
     {
          DMA_Cmd(DMA1_Channel5,DISABLE);
          Clear=USART1->SR;
          Clear=USART1->DR;    /*清除标志位*/
          DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel5);
  
          for(i=0;i<DATA_LEN;i++)
          {
              PRESSURE_COPY1[i]=PRESSURE[i];
              PRESSURE_COPY2[i]=PRESSURE[i];
              PRESSURE_COPY3[i]=PRESSURE[i];    /*将压力字符串复制3份已备切割*/
          }
         temp1=StringCut1(PRESSURE_COPY1);
         temp2=StringCut2(PRESSURE_COPY2);
         temp3=StringCut3(PRESSURE_COPY3);
  
         DMA_SetCurrDataCounter(DMA1_Channel5,PRESSURE_LENGTH);
         n=DMA1_Channel5->CNDTR;
         DMA_Cmd(DMA1_Channel5,ENABLE);
    }
}
自定义的字符串切割函数
char* StringCut1(char string[])
{
     char*temp = strtok(string,":");
     temp=strtok(NULL,":");
     return temp;
}
char* StringCut2(char string[])
{
     char*temp = strtok(string,":");
     temp=strtok(NULL,":");
     temp=strtok(NULL,":");
     temp=strtok(NULL,":");
     return temp;
}
char* StringCut3(char string[])
{
     char*temp = strtok(string,":");
     temp=strtok(NULL,":");
     temp=strtok(NULL,":");
     temp=strtok(NULL,":");
     temp=strtok(NULL,":");
     return temp;
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-11-26 00:49:42 | 显示全部楼层
回复

使用道具 举报

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
 楼主| 发表于 2017-11-26 18:04:12 | 显示全部楼层
您有没有遇到过类似的问题呢?
回复

使用道具 举报

28

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
494
金钱
494
注册时间
2017-10-14
在线时间
76 小时
发表于 2018-10-26 15:52:22 | 显示全部楼层
建议中断里不要做过多处理,把接收到的数据先存起来,在主函数里处理,个人感觉可能是你中断里占用的时间太多了导致的,不知道说的对不对,提供个参考
回复

使用道具 举报

12

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2018-2-11
在线时间
38 小时
发表于 2018-11-6 09:55:14 | 显示全部楼层
同意楼上说法,中断只需要把数据存起来,其它在主函数里面处理。中断里面可以判断下开头和结尾,数据格式都是清楚的,在主函数提取相应的字符就可以了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-5 19:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表