从零开始的STM32F1课程学习(STM32CubeMX)

新学期新气象,新学期我们要学32了,之前虽然学了一点点,但是学的都不是很系统,这里终于能系统的学习一下32了,从原理角度进行一下学习。

文章目录

    • 我的基本配置:STM32CubeMX、Jlink、STM32F103RCT6 MINI
    • 第一节课
      • 第一节课课后练习:点灯
        • 1.配置好Cube的Project Manager
        • 2.时钟树设置
        • 3.RCC设置
        • 4.Debug模式设置
        • 5.LED0引脚设置
        • 6.生成代码
        • 7.在主函数while中写出灯的亮灭
        • 8.配置Jlink
        • 9.检测芯片
        • 10.编译后下载
    • 第二节课
      • 第二节课课后练习:按键控制灯的亮灭
        • 1.配置好基础配置,和上面前4步一样
        • 2.启用按键和LED的引脚
        • 3.配置好GPIO
        • 4.在while中写出按键检测
        • 5.编译后下载成功
    • 第三节课
      • 第三节课课后练习:外部中断控制灯
        • 1.配置好基础配置,和第一节课4步一样
        • 2.配置按键的GPIO模式
        • 3.在主函数中让程序执行LED0的亮灭
        • 4. 在stm32f1xx_hal_gpio.c中找到中断回调函数
        • 5.编译后成功下载
    • 第四节课
      • 第四节课课后练习:在while(1)中执行灯的同步闪烁,按下KEY0按键,灯闪烁加快20次,按下WKUP,灯交替闪烁20次,KEY0的优先级更高
        • 1.配置好基础配置
        • 2.配置按键的GPIO
        • 3.在NVIC中配置中断优先级
        • 4.配置两个灯为推挽输出
        • 5.在while(1)中写出同步闪烁
        • 6.在stm32f10x_hal_gpio.c中写中断回调函数
        • 7.编译成功后下载
    • 第五节课
      • 第五节课课后练习:定时器实现灯的500ms间隔闪烁,和另一个灯的700ms闪烁
        • 1.配置好基础配置
        • 2.打开TIM2和TIM3
        • 3.在NVIC中设置优先级
        • 4.设置灯为推挽输出
        • 5.打开定时器中断
        • 6.编译后成功下载
    • 第六节课
      • 第六节课课后练习:通过两个按键利用PWM控制灯的亮灭
        • 1.配置好基础配置
        • 2.打开TIM1_CH1
        • 2.在NVIC中打开中断
        • 3.设置两个按键的GPIO
        • 4.写出按键检测代码和启动PWM
        • 5.编译后下载
    • 第七节课
      • 第七节课课后作业:串口的收发回显测试
        • 1.配置好基础配置
        • 2.打开串口
        • 3.在main.c中添加fputc fgetc
        • 4.主函数代码
        • 5.编译下载

我的基本配置:STM32CubeMX、Jlink、STM32F103RCT6 MINI

STM32MINI就是我们学校上课用的32
从零开始的STM32F1课程学习(STM32CubeMX)_第1张图片

第一节课

嵌入式就是在单片机上跑操作系统


STM32芯片内部
从零开始的STM32F1课程学习(STM32CubeMX)_第2张图片
这是STM32的命名规则
从零开始的STM32F1课程学习(STM32CubeMX)_第3张图片

时钟最高72M


PIN to PIN兼容是指两款芯片的引脚数目一样,功能一样,大小也一样



从零开始的STM32F1课程学习(STM32CubeMX)_第4张图片
从零开始的STM32F1课程学习(STM32CubeMX)_第5张图片
通过修改BOOT0和BOOT1的方式来修改32的启动方式,利用跳线帽改这个
从零开始的STM32F1课程学习(STM32CubeMX)_第6张图片
将2,4等引脚短接来修改其启动方式

从零开始的STM32F1课程学习(STM32CubeMX)_第7张图片
从零开始的STM32F1课程学习(STM32CubeMX)_第8张图片

第一节课课后练习:点灯

灯的连线
从零开始的STM32F1课程学习(STM32CubeMX)_第9张图片

1.配置好Cube的Project Manager

路径和工程名称设置
从零开始的STM32F1课程学习(STM32CubeMX)_第10张图片
Code Generator设置
从零开始的STM32F1课程学习(STM32CubeMX)_第11张图片

2.时钟树设置

都改成最高的
从零开始的STM32F1课程学习(STM32CubeMX)_第12张图片

3.RCC设置

从零开始的STM32F1课程学习(STM32CubeMX)_第13张图片

4.Debug模式设置

从零开始的STM32F1课程学习(STM32CubeMX)_第14张图片

5.LED0引脚设置

设置为GPIO_Output
从零开始的STM32F1课程学习(STM32CubeMX)_第15张图片

6.生成代码

从零开始的STM32F1课程学习(STM32CubeMX)_第16张图片

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

下面是标准库的配置

void LED_Init(void)
{
 GPIO_InitTypeDef GPIO_InitTypeStrucre;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 
 GPIO_InitTypeStrucre.GPIO_Mode=GPIO_Mode_Out_PP;
 GPIO_InitTypeStrucre.GPIO_Pin=GPIO_Pin_8 ;
 GPIO_InitTypeStrucre.GPIO_Speed=GPIO_Speed_50MHz;

 GPIO_Init(GPIOA,&GPIO_InitTypeStrucre); 
 GPIO_SetBits(GPIOA,GPIO_Pin_8 );
}

7.在主函数while中写出灯的亮灭

HAL_Delay(1)实际延时时间多于1ms一点

/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(300);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
		HAL_Delay(300);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);

8.配置Jlink

从零开始的STM32F1课程学习(STM32CubeMX)_第17张图片

9.检测芯片

注意:要先给芯片上电,再连接Jlink
从零开始的STM32F1课程学习(STM32CubeMX)_第18张图片

10.编译后下载

在这里插入图片描述

第二节课

什么是看门狗?

是一个定时器,将里面的数值加到一定数值之后,会被复位

所以在程序中每隔多少秒要把看门狗复位

看门狗主要用于无人看管的程序,防止程序跑飞了

GPIO:General Purpose Input Output,通用输入输出
输出三种:1.推挽2.开漏3.关闭
从零开始的STM32F1课程学习(STM32CubeMX)_第19张图片

第二节课课后练习:按键控制灯的亮灭

1.配置好基础配置,和上面前4步一样

2.启用按键和LED的引脚

从零开始的STM32F1课程学习(STM32CubeMX)_第20张图片

3.配置好GPIO

KEY0采用上拉模式和输入模式
我一般习惯把名字起的和原理图一模一样,这样代码读起来方便
从零开始的STM32F1课程学习(STM32CubeMX)_第21张图片

4.在while中写出按键检测

  while (1)
  {
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==GPIO_PIN_RESET)
		{	
			HAL_Delay(10);
			if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==GPIO_PIN_RESET)
			{	
				HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
				while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==GPIO_PIN_RESET);
			}
		}
    /* USER CODE END WHILE */
  }

5.编译后下载成功

下载后要先按一下Reset才能成功执行

第三节课

第三节课课后练习:外部中断控制灯

1.配置好基础配置,和第一节课4步一样

从零开始的STM32F1课程学习(STM32CubeMX)_第22张图片
从零开始的STM32F1课程学习(STM32CubeMX)_第23张图片

2.配置按键的GPIO模式

从零开始的STM32F1课程学习(STM32CubeMX)_第24张图片

3.在主函数中让程序执行LED0的亮灭

让LED0闪烁,LED1灭

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_Delay(300);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
		HAL_Delay(300);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
  }

4. 在stm32f1xx_hal_gpio.c中找到中断回调函数

如果按下按键,则LED1亮,表示进入外部中断

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
	if(GPIO_Pin==GPIO_PIN_1)
  {
  
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_1)==0)
    {
     HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
    }
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);
  }
}

5.编译后成功下载

第四节课

第四节课系统学习了外部中断

第四节课课后练习:在while(1)中执行灯的同步闪烁,按下KEY0按键,灯闪烁加快20次,按下WKUP,灯交替闪烁20次,KEY0的优先级更高

1.配置好基础配置

2.配置按键的GPIO

在CUBE中都设置为GPIO_EXTI模式
从零开始的STM32F1课程学习(STM32CubeMX)_第25张图片
因为KEY0接地,我们配置成上拉模式
从零开始的STM32F1课程学习(STM32CubeMX)_第26张图片
同理,配置WKUP
从零开始的STM32F1课程学习(STM32CubeMX)_第27张图片

3.在NVIC中配置中断优先级

数字越小,优先级越高
在这里插入图片描述

4.配置两个灯为推挽输出

从零开始的STM32F1课程学习(STM32CubeMX)_第28张图片

5.在while(1)中写出同步闪烁

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		delay_ms(500);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		delay_ms(500);
  }
  /* USER CODE END 3 */

delay_ms

//毫秒延时
void delay_ms(uint16_t nms)
{
 uint32_t temp;
 SysTick->LOAD = 9000*nms;
 SysTick->VAL=0X00;//清空计数器
 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}

6.在stm32f10x_hal_gpio.c中写中断回调函数

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	

  
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */

		if(GPIO_Pin==GPIO_PIN_1)
  {
  
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_1)==0)
    {
			for(int i=0;i<20;i++)
				{	
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET);
			delay_ms(200);
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET);
			delay_ms(200);
			
				}
			}
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);
	}
		if(GPIO_Pin==GPIO_PIN_0)
  {
  
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
    {
			for(int i=0;i<20;i++)
				{	
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET);
			delay_ms(200);
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET);
			delay_ms(200);
				}
		}
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
	}
	
}

7.编译成功后下载

在这个作业中不要将按键设置成浮空,浮空状态会有点问题,要根据引脚设置成需要的状态

第五节课

  • 高级定时器 TIM1 TIM8 在APB1上
  • 通用定时器 TIM2 TIM3 TIM4 TIM5 在APB2上
  • 基本定时器 TIM6 TIM7 在APB1上

从零开始的STM32F1课程学习(STM32CubeMX)_第29张图片
周期表
p n u m 1 K M G T
更新事件Update event(UE)
可以把CNT清零
在这里插入图片描述

定时器时间t=1/Tout

如果使能影子寄存器,影子寄存器会在更新事件发生时,将内部数值更新到ARR

ARR是计算时间间隔所以要加1
因为PSC不能为0,所以要加上1
从零开始的STM32F1课程学习(STM32CubeMX)_第30张图片

第五节课课后练习:定时器实现灯的500ms间隔闪烁,和另一个灯的700ms闪烁

1.配置好基础配置

2.打开TIM2和TIM3

从零开始的STM32F1课程学习(STM32CubeMX)_第31张图片
arr和psc的计算过程

(4999+1)*(7199+1)=36000000
72000000/36000000=2
1/2=0.5s=500ms

从零开始的STM32F1课程学习(STM32CubeMX)_第32张图片

3.在NVIC中设置优先级

从零开始的STM32F1课程学习(STM32CubeMX)_第33张图片

4.设置灯为推挽输出

从零开始的STM32F1课程学习(STM32CubeMX)_第34张图片

5.打开定时器中断

main.c

/* USER CODE BEGIN PV */
static int i=0;
/* USER CODE END PV */
  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start_IT(&htim3);
  /* USER CODE END 2 */

在stm32f10x_hal_tim.c中找到中断回调函数,在main.c中重定义

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim==&htim2)
  {
    HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);//对GPIO口的电平进行反转(低-高,高—低)
  }
	if(htim==&htim3)
  {
		if(++i>=700)
		{
		i=0;
    HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_2);//对GPIO口的电平进行反转(低-高,高—低)
		}
  }
	

6.编译后成功下载

第六节课

第六节课课后练习:通过两个按键利用PWM控制灯的亮灭

1.配置好基础配置

2.打开TIM1_CH1

从零开始的STM32F1课程学习(STM32CubeMX)_第35张图片

2.在NVIC中打开中断

从零开始的STM32F1课程学习(STM32CubeMX)_第36张图片

3.设置两个按键的GPIO

从零开始的STM32F1课程学习(STM32CubeMX)_第37张图片

4.写出按键检测代码和启动PWM

/* USER CODE BEGIN 1 */
	int i=500;
  /* USER CODE END 1 */
  /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);  // 使能PWM输出
  /* USER CODE END 2 */
    /* USER CODE BEGIN 3 */
		if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_1)==GPIO_PIN_RESET)
		{	
			HAL_Delay(10);
			if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_1)==GPIO_PIN_RESET)
			{	
				i=i+1;
				htim1.Instance->CCR1 = i; 
				HAL_Delay(1);
				while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_1)==GPIO_PIN_RESET);
			}
		}
		if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==GPIO_PIN_RESET)
		{	
			HAL_Delay(10);
			if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==GPIO_PIN_RESET)
			{	
				i=i-1;
				htim1.Instance->CCR1 = i; 
				HAL_Delay(1);
				while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==GPIO_PIN_RESET);
			}
		}
  }
  /* USER CODE END 3 */

5.编译后下载

第七节课

第七节课课后作业:串口的收发回显测试

1.配置好基础配置

2.打开串口

设置异步模式和打开中断
从零开始的STM32F1课程学习(STM32CubeMX)_第38张图片

3.在main.c中添加fputc fgetc

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

4.主函数代码

定义了一个字符串

/* USER CODE BEGIN 1 */
	char str[10];
  /* USER CODE END 1 */

因为scanf在单片机中并不是阻塞式接收,所以我们要将其改为阻塞式的

/* USER CODE BEGIN 3 */
			printf("测试发送\n");
			HAL_Delay(100);
			 str[0]=0;
		  while(str[0] == 0)
		  	{
			scanf("%s",str);
				}//使其变成手动的阻塞式接收
			HAL_Delay(1000);
			printf("output:%s\n",str);

5.编译下载

可以发送也可以接收
从零开始的STM32F1课程学习(STM32CubeMX)_第39张图片

你可能感兴趣的:(stm32,学习,单片机)