OpenEdv-开源电子网

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

串口接收到数据后RXNE不被置位

[复制链接]

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
发表于 2017-11-27 15:52:16 | 显示全部楼层 |阅读模式
6金钱
问题描述:
     最近在做一个关于串口读压力模块压力值的项目,用到的压力模块的基本工作原理为,通过串口向压力模块发送读压力指令"1:R:MRMD:0:0"(字符串),压力模块会返回压力值字符串"1:F:MRMD:101.00:KPA"(非定长字符串),收到压力值字符串后需要对其进行分割,以提取标识位'F'、压力值'101.00',以及压力单位'KPA'。
     我做该项目的思路是通过DMA传输的方式将串口接收到的压力字符串从串口数据寄存器传输到内存,通过串口的总线空闲中断(IDLE)判断压力值字符串是否接收完成,若接收完成触发中断程序,在中断程序中对字符串中进行分割并提取具有关键值的子串。
     在调试程序的过程中,通过keil仿真器仿真过程中rxne状态位在接收到字符串后始终不会被置位,导致空闲中断不被响应,最终导致压力字符串没不能被有效处理,刚接触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_ITConfig(USART1,USART_IT_RXNE,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劲爆上市
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-11-27 17:28:09 | 显示全部楼层
本帖最后由 aiyeba 于 2017-11-27 17:36 编辑

把接收中断关掉试试.   有了接收完成中断就不要这个接收中断了.

而且你的好像没有清除标志位的处理哦,在中断里面.

忘了告诉你了,    如果单一的接收中断.每接收一个字节就会进来一次.

而接收完成中断需要接收到一包数据才会进来.  他的判断依据就是10ms内没有再接收到数据了,不过这个不需要你来判断.属于DMA的内部机制.

自己选择的路,成家前走完。
回复

使用道具 举报

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
 楼主| 发表于 2017-11-27 20:55:17 | 显示全部楼层
aiyeba 发表于 2017-11-27 17:28
把接收中断关掉试试.   有了接收完成中断就不要这个接收中断了.

而且你的好像没有清除标志位的处理哦,在 ...

您说的接收中断是否是 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);这句呢?
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-11-28 10:52:45 | 显示全部楼层
lidi90hou 发表于 2017-11-27 20:55
您说的接收中断是否是 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);这句呢?

对,不用这个.
自己选择的路,成家前走完。
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-11-28 10:55:05 | 显示全部楼层
自己选择的路,成家前走完。
回复

使用道具 举报

28

主题

133

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
323
金钱
323
注册时间
2016-11-22
在线时间
66 小时
发表于 2017-11-28 15:11:38 | 显示全部楼层
本帖最后由 ARM学员 于 2017-11-28 15:18 编辑

既然是刚接触STM32,推荐你去看看ST官方提供的代码例程。 QQ截图1.png 这里面芯片的外设配置基本都有了,而且ST官方肯定是测试过的,放心使用。从你的代码不难看出是摘抄网上的,摘抄网上的代码有一个最大的问题就是这个代码适合发布者的开发板,不一定适合你的开发板,如果你一定要用别人的代码,那么首先你要完全看懂这份代码。这是一种学习方法,比起解决你目前这个问题更有价值吧。
回复

使用道具 举报

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
 楼主| 发表于 2017-11-28 16:34:16 | 显示全部楼层
ARM学员 发表于 2017-11-28 15:11
既然是刚接触STM32,推荐你去看看ST官方提供的代码例程。这里面芯片的外设配置基本都有了,而且ST官方肯定 ...

谢谢您的建议
回复

使用道具 举报

2

主题

6

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2017-11-23
在线时间
3 小时
 楼主| 发表于 2017-11-28 16:53:54 | 显示全部楼层
aiyeba 发表于 2017-11-28 10:55
http://www.openedv.com/forum.php?mod=viewthread&tid=63849

谢谢您的回复,我按照您的建议修改了代码,但是RXNE仍不能置位,但是空闲中断只有接收到‘0’才中断,若收到的字符串中没有'0'仍然不会进入空闲中断。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-13 06:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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