上次写RFID节点时遇到一个问题就是zigbee指令怎么接收
我用了多套方案
先说下模型
用电脑A使用c8t6为mcu,串口一接zigbee,串口2接电脑A
用电脑B使用用usb转ttl直接和电脑的串口助手通信
第一套是用输入输出重定向,直接getchar但是不对,只有前几个可以接收后面接收不到了
第二套是在中断处理函数里直接调用串口二给电脑打印
同样出现了只有前几个可以接收到后面就接收不到了。
所以我和我的搭档配合了一下,让他使用mdk5的debug模式硬件仿真,看看接收后会卡在哪里。
测试后发现卡在了中断处理函数中
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE));
就是这句
之前是为了判断他上次是否发送完了所以写了这个,结果就一直在while出不来了。所以我注释掉了这句话,结果非常之好使。
然后因为只有回传不行呀,又进行控制指令测试
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "stdio.h"
u16 res=0;
void MyUSART1_Init(void){//PA9->TX PA10->RX tx是表示发送 (transport),rx是表示接收 (receive)
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitSture;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能串口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_DeInit(USART1);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;//配置GPIO
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitSture.USART_BaudRate =115200;//配置串口
USART_InitSture.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
USART_InitSture.USART_Mode =(USART_Mode_Rx|USART_Mode_Tx);
USART_InitSture.USART_Parity =USART_Parity_No;
USART_InitSture.USART_StopBits =USART_StopBits_1;
USART_InitSture.USART_WordLength =USART_WordLength_8b;
USART_Init(USART1,&USART_InitSture);
NVIC_InitStrue.NVIC_IRQChannel =USART1_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd =ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority =2;
NVIC_Init(&NVIC_InitStrue);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启接受中断
USART_Cmd(USART1,ENABLE);
}
void MyUSART2_Init(void){//PA2->TX PA3->RX tx是表示发送 (transport),rx是表示接收 (receive)
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitSture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能串口
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;//配置GPIO
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitSture.USART_BaudRate =115200;//配置串口
USART_InitSture.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
USART_InitSture.USART_Mode =(USART_Mode_Rx|USART_Mode_Tx);
USART_InitSture.USART_Parity =USART_Parity_No;
USART_InitSture.USART_StopBits =USART_StopBits_1;
USART_InitSture.USART_WordLength =USART_WordLength_8b;
USART_Init(USART2,&USART_InitSture);
USART_Cmd(USART2,ENABLE);
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
MyUSART1_Init();
MyUSART2_Init();
delay_init();
LED_Init();
while (1){
if(res!=0){
USART_SendData(USART2,res);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
delay_ms(500);
}else{
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
}
}
void USART1_IRQHandler(void){
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志.
res =USART_ReceiveData(USART1);
USART_SendData(USART1,USART_ReceiveData(USART1));
USART_SendData(USART2,USART_ReceiveData(USART1));
//while(USART_GetFlagStatus(USART1,USART_FLAG_TXE));
}
}
结果根本控制不了。
然后使用串口助手的转16进制试了一下
发现我发了一个0他发送了三个字节
30 0D 0A
查询ASCII表发现是0\r\n的意思。
瞬间悟了这不是windows的回车么
linux的回车只有一个\n就行但是windows不是
所以我读不到控制指令也许是这个问题
/**
* @brief Checks whether the specified USART flag is set or not.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5)
* @arg USART_FLAG_LBD: LIN Break detection flag
* @arg USART_FLAG_TXE: Transmit data register empty flag
* @arg USART_FLAG_TC: Transmission Complete flag
* @arg USART_FLAG_RXNE: Receive data register not empty flag
* @arg USART_FLAG_IDLE: Idle Line detection flag
* @arg USART_FLAG_ORE: OverRun Error flag
* @arg USART_FLAG_NE: Noise Error flag
* @arg USART_FLAG_FE: Framing Error flag
* @arg USART_FLAG_PE: Parity Error flag
* @retval The new state of USART_FLAG (SET or RESET).
*/
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_FLAG(USART_FLAG));
/* The CTS flag is not available for UART4 and UART5 */
if (USART_FLAG == USART_FLAG_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
这是这个函数的源码
追一下assert_param
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
就是一个检查函数参数的变量
#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
((PERIPH) == USART2) || \
((PERIPH) == USART3) || \
((PERIPH) == UART4) || \
((PERIPH) == UART5))
所有串口外设的宏
#define IS_USART_FLAG(FLAG) (((FLAG) == USART_FLAG_PE) || ((FLAG) == USART_FLAG_TXE) || \
((FLAG) == USART_FLAG_TC) || ((FLAG) == USART_FLAG_RXNE) || \
((FLAG) == USART_FLAG_IDLE) || ((FLAG) == USART_FLAG_LBD) || \
((FLAG) == USART_FLAG_CTS) || ((FLAG) == USART_FLAG_ORE) || \
((FLAG) == USART_FLAG_NE) || ((FLAG) == USART_FLAG_FE))
所有串口标志的宏
CTS是通用类型系统
LIN是本地互联网络
也就是说当
USARTx->SR 和 USART_FLAG
是高电平时返回高电平是低电平时返回低电平
所以一直在循环是因为这两个一直都是高电平
但是为什么一直是高电平暂时不清楚
---------------------------------------------------------------------------------------------------------------------------------
已经三天了感觉自己好废啊,学了快三年的嵌入式和物联网串口都搞不好,被淘宝客服嘲笑
丢脸啊
算了不破不立,直接重写,遇到解决不了的bug最好的办法就是重来一次
---------------------------------------------------------------------------------------------------------------------------------
为了搞这个我又重新学了一遍32换了一个库用hal库试一试
因为标准库不好使,我用寄存器却没问题,感觉可能是设置问题
---------------------------------------------------------------------------------------------------------------------------------
终于好了,应该就是我人菜,学的太浅了,这次我大道至简,用cubemx生成俩串口,在串口中断回调里处理一点问题都木有。
左面是单片机串口一右面是直接插在电脑上的zigbee
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* © Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
uint8_t aRxBuffer[2];
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t txbuf[100];
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
memcpy(txbuf,"这是一个串口中断接收回显实验\n",100);
HAL_UART_Transmit(&huart1,txbuf,strlen((char *)txbuf),1000);
HAL_UART_Transmit(&huart2,txbuf,strlen((char *)txbuf),1000);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* 使能接收,进入中断回调函数 */
HAL_UART_Receive_IT(&huart1,&aRxBuffer[0],1);
HAL_UART_Receive_IT(&huart2,&aRxBuffer[1],1);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle==&huart1)
{
HAL_UART_Transmit(&huart2,&aRxBuffer[0],1,0);
HAL_UART_Receive_IT(&huart1,&aRxBuffer[0],1);
}
else if(UartHandle==&huart2)
{
HAL_UART_Transmit(&huart1,&aRxBuffer[1],1,0);
HAL_UART_Receive_IT(&huart2,&aRxBuffer[1],1);
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
精华都在主函数里,剩下的都是cubemx生成的