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
- 硬件外观:
- 引脚配置:
实现
核心代码
- 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);
- 使用内部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);
- 串口多字节收发
[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);
}
- 主函数
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 */
}
效果