P7 STM32的定时器与串口综合训练

一,实训:定时器与串口综合训练

【1】开机后,LED1 LED2依次点亮,然后熄灭,进行灯光检测。
LED1 接到STM32的PB3,LED2接到STM32的PB4,低电平点亮。
【2】系统通过串口1向上位机发送一个字符串"XMF07欢迎你!”
【3】LED1 作为一个秒闪灯,系统向上位机发送完字符串后,开始亮0.5秒,灭0.5秒…循环闪烁,并开始启动系统运行时间的记录,其时分秒格式为“XX:XX:XX”
【4】上位机通过一个由3个字节组成的命令帧控制LED2灯的开关。该命令帧的格式为“0xBF 控制字 0xFB”
  0xBF为帧头,0xFB为帧尾控制字的定义如下:
  0xA1:打开LED2,返回信息“XX:XX:XX LED2打开。
  0xA2:关闭LED2,返回信息“XX:XX:XX LED2关闭。
  其他:返回信息“XX:XX:XX 这个一个错误指令!”。

二,STM32CubeMX中的配置

1.新建工程,根据自己的开发板选择芯片

在这里插入图片描述在这里插入图片描述

2.配置参数

①配置RCC和SYS

在这里插入图片描述
在这里插入图片描述

②配置定时器

 i)将时钟频率设置为32MHZ
在这里插入图片描述

 ii)根据题目,需要实现亮0.5秒,然后灭0.5秒…。在时钟频率为32MHz的前题下,可以设Prescaler为32000-1,Counter Period为500-1
在这里插入图片描述

 使用定时器中断
在这里插入图片描述

③根据题目需求,配置串口

在这里插入图片描述

 打开串口中断
在这里插入图片描述

④配置LED

 将PB3和PB4设置为GPIO_Output
在这里插入图片描述

3.配置工程,并创建工程

在这里插入图片描述
在这里插入图片描述
 生成代码
在这里插入图片描述

三,在MDK上编写代码,实现需求

1.需求一:开机后,LED1 与LED2依次点亮,然后熄灭,进行灯光检测。

  在main.c的CODE BEGIN 2 处写如下代码可实现

 /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET);
  HAL_Delay(500);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
  HAL_Delay(500);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
  /* USER CODE END 2 */

2.需求二:系统通过串口1向上位机发送一个字符串"XMFO7欢迎你!”。

  接在需求一的代码最后处可以实现该任务

HAL_UART_Transmit(&huart1,"XMF07欢迎你!",sizeof("XMF07欢迎你!"),10000);

在这里插入图片描述

3.需求三:LED1作为一个秒闪灯,系统向上位机发送完字符串后,开始亮0.5秒,灭0.5秒…循环闪烁,并开始启动系统运行时间的记录,其时分秒格式为“XX:XX:XX”。

①重写定时器相关的虚函数

在这里插入图片描述

②在需求二的最末尾处接上定时器的启动代码
HAL_TIM_Base_Start_IT(&htim2);
③在CODE BEGIN 0处写需求三的相关代码
/* USER CODE BEGIN 0 */
unsigned char hour = 0;
unsigned char minute = 0;
unsigned char second = 0;
unsigned char halfSecond = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3);
halfSecond++;
}
if(halfSecond == 2)
{
halfSecond = 0;
second++;
}
if(second == 60)
{
second = 0;
minute++;
}
if(minute == 60)
{
minute = 0;
hour++;
}
}

/* USER CODE END 0 */

4.需求四:上位机通过一个由3个字节组成的命令帧控制LED2灯的开关。该命令帧的格式为“0xBF 控制字 0xFB”。

  0xBF为帧头,0xFB为帧尾,控制字的定义如下:
  0xA1:打开LED2,返回信息“XX:XX:XX LED2打开。”
  0xA2:关闭LED2,返回信息“XX:XX:XX LED2关闭。”
  其他:返回信息“XX:XX:XX 这个一个错误指令!”。

①在HAL_TIM_Base_Start_IT(&htim2);代码后接上串口接收的相关代码
HAL_UART_Receive_IT(&huart1,&Rxd_Date,3);

在这里插入图片描述

②在CODE BEGIN 0需求三的相关代码后面写如下代码
unsigned char Rxd_Date[3];
unsigned char Txd_Data1[]="00: 00: 00 LED2打开";
unsigned char Txd_Data2[]="00: 00: 00 LED2关闭";
unsigned char Txd_Data3[]="00: 00: 00 这是一个错误指令!";
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
Txd_Data1[0] = Txd_Data2[0] = Txd_Data3[0] = hour / 10 +0x30;
Txd_Data1[1] = Txd_Data2[1] = Txd_Data3[1] = hour % 10 +0x30;
Txd_Data1[4] = Txd_Data2[4] = Txd_Data3[4] = minute / 10 +0x30;
Txd_Data1[5] = Txd_Data2[5] = Txd_Data3[5] = minute % 10 +0x30;
Txd_Data1[8] = Txd_Data2[8] = Txd_Data3[8] = second / 10 +0x30;
Txd_Data1[9] = Txd_Data2[9] = Txd_Data3[9] = second % 10 +0x30;
if(huart->Instance == USART1)
{
if(Rxd_Date[0] == 0xBF && Rxd_Date[2] == 0xFB)
{
if(Rxd_Date[1] == 0xA1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_UART_Transmit(&huart1,Txd_Data1,sizeof(Txd_Data1),10000);
}
else if(Rxd_Date[1] == 0xA2)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
HAL_UART_Transmit(&huart1,Txd_Data2,sizeof(Txd_Data2),10000);
}
else
{
HAL_UART_Transmit(&huart1,Txd_Data3,sizeof(Txd_Data3),10000);
}
}
              else
      {
    HAL_UART_Transmit(&huart1,Txd_Data3,sizeof(Txd_Data3),10000);
      }
}
HAL_UART_Receive_IT(&huart1,Rxd_Date,3);
}

在这里插入图片描述

四,使用sprintf()函数

1.指的是字符串格式化函数,把格式化的数据写入某个字符串中。
int sprintf(char *string,char *format [,argument,.]);
  引入头文件 #include “stdio.h”
  例:有一个表示温度的整型变量tmp,现在要将其格式化为字符串“温度是:XX摄氏度”,并将其通过串口1发送出去。

uint8_t Str_buff[64];
sprintf((char*)Str_buff,"温度是:%d摄氏度",tmp);

2.使用sprintf()函数更改训练代码
  1)在main.c文件中加上头文件"stdio.h"
在这里插入图片描述
  2)更改main.c文件中USER CODE BEGIN 0处的代码

/* USER CODE BEGIN 0 */
unsigned char hour = 0;
unsigned char minute = 0;
unsigned char second = 0;
unsigned char halfSecond = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3);
halfSecond++;
}
if(halfSecond == 2)
{
halfSecond = 0;
second++;
}
if(second == 60)
{
second = 0;
minute++;
}
if(minute == 60)
{
minute = 0;
hour++;
}
}

unsigned char Rxd_Date[3];
unsigned char Str_buff[64];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
if(Rxd_Date[0] == 0xBF && Rxd_Date[2] == 0xFB)
{
if(Rxd_Date[1] == 0xA1)
{
sprintf((char*)Str_buff,"%d: %d: %d LED2打开", hour, minute, second);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_UART_Transmit(&huart1,Str_buff,sizeof(Str_buff),10000);
}
else if(Rxd_Date[1] == 0xA2)
{
sprintf((char*)Str_buff,"%d: %d: %d LED关闭", hour, minute, second);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
HAL_UART_Transmit(&huart1,Str_buff,sizeof(Str_buff),10000);
}
else
{
sprintf((char*)Str_buff,"%d: %d: %d 这是一个错误指令", hour, minute, second);
HAL_UART_Transmit(&huart1,Str_buff,sizeof(Str_buff),10000);
}
}
else
{
sprintf((char*)Str_buff,"%d: %d: %d 这是一个错误指令", hour, minute, second);
HAL_UART_Transmit(&huart1,Str_buff,sizeof(Str_buff),10000);
}

}
HAL_UART_Receive_IT(&huart1,Rxd_Date,3);
}

/* USER CODE END 0 */
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在STM32F103芯片上使用定时器输出PWM信号的示例代码,使用了P3、P4、P5、P6、P7、P8、P9端口: ```c #include "stm32f10x.h" void GPIO_Configuration(void); void TIM_Configuration(void); int main(void) { GPIO_Configuration(); TIM_Configuration(); while (1) { } } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = 1999; // 1 kHz PWM frequency TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 72 MHz / 72 = 1 MHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC3Init(TIM3, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC4Init(TIM3, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OC5Init(TIM3, &TIM_OCInitStructure); TIM_OC5PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC6Init(TIM3, &TIM_OCInitStructure); TIM_OC6PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_Cmd(TIM3, ENABLE); } ``` 这段代码使用了定时器 TIM3 来输出 PWM 信号,其频率为 1 kHz,占空比可以通过修改 `TIM_OCInitStructure.TIM_Pulse` 来调整。同时,定时器的时钟源使用的是 APB1 总线,其时钟频率为 72 MHz,因此需要将 `TIM_TimeBaseStructure.TIM_Prescaler` 设为 72-1,以得到 1 MHz 的时钟信号。输出端口使用的是 GPIOB 3~9 口,使用复用功能输出 PWM 信号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值