stm32笔记[7]-串口多字节收发

主要功能

使用Alios Things Dev kit 开发板实现串口多字节收发,使用内部RTC时钟和AD转换.

硬件平台

  • 开发板:Alios Things Dev kit
  • 芯片:stm32l496vgt6
  • 系统时钟:80MHz
  • LED1:PB6(低电平有效)
  • LED2:PE3(低电平有效)
  • LED3:PD15(低电平有效)
  • STLK_TX:PB10(LPUART1)
  • STLK_RX:PB11(LPUART1)
  • ADC1_IN7:PA2
  • 硬件外观:
    硬件外观
  • 引脚配置:
    引脚配置

实现

核心代码

  1. ADC转换
//初始化ADC
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
//读取ADC的值
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
uint16_t adc_value = HAL_ADC_GetValue(&hadc1);
char buffer[32];
sprintf(buffer, "ADC value: %d\r\n", adc_value);
lpuart1_printf(buffer);
  1. 使用内部RTC时钟
//初始化
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x23;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_TUESDAY;
  sDate.Month = RTC_MONTH_MAY;
  sDate.Date = 0x23;
  sDate.Year = 0x2023;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

//读取RTC的值
char b3[32];
HAL_RTC_GetTime(&hrtc, &RTC_TimeStruct, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &RTC_DateStruct, RTC_FORMAT_BIN);
sprintf(b3,"Time:%02d-%02d-%02d %02d:%02d:%02d\n",RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date,RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
lpuart1_printf(b3);
  1. 串口多字节收发
    [https://wenku.baidu.com/view/8b68ca5f24284b73f242336c1eb91a37f1113235.html?fr=sogou&wkts=1684850474131]
    主要方法:主要使用HAL库,在处理接收中断时读取寄存器UART_FLAG_RXNE的值,在处理空闲中断时读取空闲中断寄存器UART_FLAG_IDLE的值。
    main.c
//串口配置
static void MX_LPUART1_UART_Init(void)
{

  /* USER CODE BEGIN LPUART1_Init 0 */

  /* USER CODE END LPUART1_Init 0 */

  /* USER CODE BEGIN LPUART1_Init 1 */

  /* USER CODE END LPUART1_Init 1 */
  hlpuart1.Instance = LPUART1;
  hlpuart1.Init.BaudRate = 115200;
  hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart1.Init.StopBits = UART_STOPBITS_1;
  hlpuart1.Init.Parity = UART_PARITY_NONE;
  hlpuart1.Init.Mode = UART_MODE_TX_RX;
  hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LPUART1_Init 2 */
  //添加空闲中断
  HAL_NVIC_EnableIRQ(LPUART1_IRQn);
  HAL_NVIC_SetPriority(LPUART1_IRQn,3,3);

  __HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_RXNE);//接收中断
  __HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_IDLE);//空闲中断
  /* USER CODE END LPUART1_Init 2 */

}

//串口打印函数
void lpuart1_printf(char * input){
		  char b2[32];
		  snprintf(b2, sizeof(b2), "log:%s\n", input);
		  HAL_UART_Transmit(&hlpuart1, (uint8_t *)b2, strlen(b2), strlen(b2) * 10);
}

stm32l4xx_it.c

//串口中断回调函数
void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */
	//自动调用HAL_UART_RxCpltCallback()
		uint8_t rec; // 暂存接收到的数据
		//接收中断
			if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET) {
			    HAL_UART_Receive(&hlpuart1, &rec, 1, 1000);
			    if (matter_frame_buffer_pos < 256) { // 确保不会溢出
			    	matter_frame_buffer[matter_frame_buffer_pos++] = rec; // 存储数据并更新长度
			    }
			    //清除中断接收标志
			    __HAL_UART_CLEAR_FLAG(&hlpuart1,UART_FLAG_RXNE);

			}
		//空闲中断
			if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE) != RESET){
				//接收完成一帧数据
				LPUART_IdleCallback(matter_frame_buffer,matter_frame_buffer_pos);


				 //清除中断接收标志
				__HAL_UART_CLEAR_FLAG(&hlpuart1,UART_FLAG_IDLE);
			}
  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */


  /* USER CODE END LPUART1_IRQn 1 */
}

/* USER CODE BEGIN 1 */
//空闲中断回调函数
void LPUART_IdleCallback(uint8_t *pData,uint16_t len){
	//空闲中断回调
	while(__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_TC)!=SET);
	//调试:转发数据
	HAL_UART_Transmit(&hlpuart1,"Idle_Rec:",9,1000);
	HAL_UART_Transmit(&hlpuart1,matter_frame_buffer,len,1000);
	HAL_UART_Transmit(&hlpuart1,"\n",2,1000);
}
  1. 主函数
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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_DMA_Init();
  MX_TIM2_Init();
  MX_LPUART1_UART_Init();
  MX_ADC1_Init();
  MX_DAC1_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  HAL_TIM_Base_Start_IT(&htim2);//启动TIM2定时器
  //HAL_TIM_Base_Start
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);

	MatterFrame frame;
	frame.header = 0x5A;
	frame.control = 0x01;
	frame.protocolId = 0x01;
	frame.footer = 0xA5;
	char msg[] = "Hello";
	frame.data = (uint8_t *)msg;
	frame.length = strlen(msg) + 3; // control, protocolId, fcs
	frame.fcs = 0x00; // dummy value, you can calculate the real FCS if needed

	HAL_UART_Transmit(&hlpuart1, (uint8_t *)&frame, sizeof(frame), 500);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin);

	  lpuart1_printf("hello1\n");//log

	  // 生成0-3V的随机电平
	  float voltage = (float)rand() / RAND_MAX * 3.0f;
	  HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, (uint32_t)(voltage / 3.3f * 4095));

	  lpuart1_printf("hello2\n");//log

	  HAL_Delay(5000);

	  lpuart1_printf(matter_frame_buffer);

	  char b3[32];
	  HAL_RTC_GetTime(&hrtc, &RTC_TimeStruct, RTC_FORMAT_BIN);
	  HAL_RTC_GetDate(&hrtc, &RTC_DateStruct, RTC_FORMAT_BIN);
	  sprintf(b3,"Time:%02d-%02d-%02d %02d:%02d:%02d\n",RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date,RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
	  lpuart1_printf(b3);

	  // 读取PA2引脚的ADC值
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  uint16_t adc_value = HAL_ADC_GetValue(&hadc1);
	  char buffer[32];
	  sprintf(buffer, "ADC value: %d\r\n", adc_value);


	  lpuart1_printf(buffer);

	  lpuart1_printf("hello3\n");//log

	  sprintf(b3,"Rec:%s\n",matter_frame_buffer);
	  lpuart1_printf(b3);

	  lpuart1_printf("hello4\n");//log


	  //HAL_UART_Transmit(&hlpuart1, (uint8_t *)&frame, sizeof(frame), 100);
	  //HAL_UART_Transmit(&hlpuart1, frame.data, frame.length - 3, 100);
	  //receive_matter_frame(&hlpuart1, &frame);//更改为接收中断
	  //receive_matter_frame();
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

效果



posted @ 2023-06-02 19:06  qsBye  阅读(547)  评论(0编辑  收藏  举报