你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

串口输入几个细节问题请求帮助下。

[复制链接]
lvfeng123 提问时间:2019-5-3 08:02 /
第一次接触嵌入式,看了几天代码,还是稀里糊涂的,不甚清晰。请大神多指教。

我的需求: 从串口接收固定长度的字符字节。  不是该长度的放弃掉不管。符合长度的处理。下面是我的代码:
//芯片是L496
#include "main.h"
#include <stdint.h>
#define DLen 8 //用长度8测试

//定义了几个函数,写安卓,java,erlang多了,所以大括号习惯请多包涵。
void Start_Recieve(UART_HandleTypeDef *luart);
void ready_next(UART_HandleTypeDef *luart);
HAL_StatusTypeDef Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

int main(void){
        UART_HandleTypeDef Lpuart1; //虚拟串口LPUSART1

//一些初始化
  HAL_Init();
  SystemClock_Config();
  LPUART1_Init(&Lpuart1);
  LED_Init();
        if(HAL_UART_Init(&Lpuart1) == HAL_OK){
                HAL_UART_Transmit(&Lpuart1,(uint8_t *)&"\r\nInit ok!\r\n",12,0xffff);       
                while(1) Start_Recieve(&Lpuart1); //开始接收数据 (问题1????)
        }
}

void Start_Recieve(UART_HandleTypeDef *luart){
        uint8_t res[DLen];
        while(HAL_UART_GetState(luart) == HAL_UART_STATE_BUSY_RX){};
  if(Receive(luart,res,DLen,2000U) == HAL_OK) //2秒超时,不符合长度的就按照超时不管了。
                HAL_UART_Transmit(luart,res,DLen,0xFFFF);  //接收到数据的处理函数,就先输出到终端测试了。
        ready_next(luart);   //处理完,继续等待接收数据
}

//这是接收函数, 从示例代码里面模仿写的。8bit数据, 无校验,1停止
HAL_StatusTypeDef Receive(UART_HandleTypeDef *luart, uint8_t *pData, uint16_t Size, uint32_t Timeout){
  uint16_t uhMask;
  uint32_t tickstart;

  if (huart->RxState == HAL_UART_STATE_READY){
    if ((pData == NULL) || (Size == 0U))
      return  HAL_ERROR;

    __HAL_LOCK(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;
    tickstart = HAL_GetTick();
    luart->RxXferSize  = Size;
    luart->RxXferCount = Size;
    UART_MASK_COMPUTATION(huart);
    uhMask = luart->Mask;
               
    while (luart->RxXferCount > 0U){
      if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
        return HAL_TIMEOUT;
      *pData = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
      pData++;
      luart->RxXferCount--;
    }
               
    __HAL_UNLOCK(huart);

    return HAL_OK;
  }else
    return HAL_BUSY;
}

//重新把系统置为等待接收数据状态
void ready_next(UART_HandleTypeDef *luart){
        HAL_UART_IRQHandler(luart);
        __HAL_UART_ENABLE_IT(luart, UART_IT_RXNE);
        luart->RxState = HAL_UART_STATE_READY;
}



上面跑起来没有问题, 测试也正常。有几个疑问解不开:

1. while这样一直搞, 不耗电吗? 有什么好办法,比如唤醒怎么用?

2. 我设置波特率不生效, 现在设置的是115200  换成9600就不行了。 要怎么更换呢?
我这样更换不行, huart->Init.BaudRate       = 9600U;
3.超长的数据没有找到啥好办法控制。
收藏 评论3 发布时间:2019-5-3 08:02

举报

3个回答
xiaolingoei 回答时间:2019-5-3 09:21:17
1、while(1){}这里面的程序是需要重复执行的。唤醒你可以参考一下RTC、STM32休眠与唤醒
2、在上面没有看到你设置波特率的代码,拿我自己的举个例子(HAL库和标准库差不多)
  1.         //UART 初始化设置
  2.         UART1_Handler.Instance=USART1;                                            //USART1
  3.         UART1_Handler.Init.BaudRate=ui32Bound;                                //波特率
  4.         UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
  5.         UART1_Handler.Init.StopBits=UART_STOPBITS_1;            //一个停止位
  6.         UART1_Handler.Init.Parity=UART_PARITY_NONE;                    //无奇偶校验位
  7.         UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
  8.         UART1_Handler.Init.Mode=UART_MODE_TX_RX;                    //收发模式
  9.         HAL_UART_Init(&UART1_Handler);                                            //HAL_UART_Init()会使能UART1
复制代码
要更改波特率,更改UART1_Handler.Init.BaudRate=ui32Bound,中的ui32Bound即可。你写的9600U是不对的,就是9600。
3、用串口传输超长的数据,如果你要提速,尤其是对上位机通信,用串口显然是不合适的,建议换usb2.0。
如果是要保证准确率,由于串口一次一般发8bit,如果你的数据是16bit,那么就要对数据进行分割。你可以在每次发送最后设置校验位,对每次发送是否OK,进行校验。
以及,硬件上串口千万不要接线接太长,串口的RX\TX最多接30cm的线,否者误码率会提高不少。

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

lvfeng123 回答时间:2019-5-3 14:37:41
xiaolingoei 发表于 2019-5-3 09:21
1、while(1){}这里面的程序是需要重复执行的。唤醒你可以参考一下RTC、STM32休眠与唤醒
2、在上面没有看 ...

多谢解答。
void LPUART1_Init(UART_HandleTypeDef *huart){
  huart->Instance            = LPUART1;
  huart->Init.BaudRate       = 115200U;
  huart->Init.WordLength     = UART_WORDLENGTH_8B;
  huart->Init.StopBits       = UART_STOPBITS_1;
  huart->Init.Parity         = UART_PARITY_NONE;
  huart->Init.HwFlowCtl      = UART_HWCONTROL_NONE;
  huart->Init.Mode           = UART_MODE_TX_RX;
  huart->Init.OverSampling   = UART_OVERSAMPLING_16;
  huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  
        GPIO_InitTypeDef          GPIO_InitStruct;
  
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_LPUART1_CLK_ENABLE();
//__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);
  GPIO_InitStruct.Pin       = GPIO_PIN_7 | GPIO_PIN_8;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull      = GPIO_PULLUP;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
  
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);  
}
这是我的初始化配置, 115200就可以, 我修改成9600就不行了,收不到数据。不知道为什么。

超长数据,我的意思是: 如果我就指定接收200字节长的数据。 超过这个长度的我不收, 有办法控制吗?
xiaolingoei 回答时间:2019-5-4 09:13:02
你代码里面可能是有宏定义?且先撇开LPUART1、115200U这些定义不谈,在配置了UART之后,没有对它进行使能。
你按照这个和你的程序配置比对一下,算是HAL库的标准设置:
  1. void MX_USART1_UART_Init(void)
  2. {
  3.    huart1.Instance = USART1;
  4.    huart1.Init.BaudRate = 115200;
  5.    huart1.Init.WordLength = UART_WORDLENGTH_8B;
  6.    huart1.Init.StopBits = UART_STOPBITS_1;
  7.    huart1.Init.Parity = UART_PARITY_NONE;
  8.    huart1.Init.Mode = UART_MODE_TX_RX;
  9.    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  10.    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  11.    huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
  12.    huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  13.    HAL_HalfDuplex_Init(&huart1);
  14. }
复制代码
这里的接收,是用上位机软件接收还是同样的芯片USART接收?两者通信的波特率一定要匹配,9600就都要设置成9600。
超长数据的处理,我给个思路:你可以__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); ,在接收中断里面做个计数,接收200次之后关闭USART的接收功能。(PS:不只一种方法)



评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版