新建CubeMX工程

电路板简介

主控芯片:STM32G431RBT6

程序下载调试需要连接 CN2 接口(调试器的USB 转串口功能默认与STM32G431RBT6 微控制器 USART1连接)

基础CubeMX配置

  • 配置下载调试器接口 SYS—>[debug] Serial Wire

  • 开启时钟——外部高速时钟 RCC—>[High~] Crystal/Ceramic Resonator

  • 配置时钟树——官方要求80MHz

  • 文件配置

    1. 项目名称
    2. 路径(不要有中文)
    3. Project—>[Toolchain/IDE] MDK-ARM + V5.32
    4. Code—>第一个格选第二个 第二个格勾上第一个
  • 点击生成[GENERATE CODE]

新建Keil u5 基本设置

  • 魔法棒—>Target—>[ARM Compliler]use 6
  • Debug–>[Use] CMSIS-DAP–>Settings–>[flash Dowload] √Reset and Run

自动补全

  • 功能栏【Edit】—>Configuration—>【Text Completion】√ Symbols after—>OK

复位键

  • Debug–>[Use] CMSIS-DAP–>Settings–>[flash Dowload] √Reset and Run

用户自己编写的代码注意写在区域里,不然重新生成 CubeMX 会没了

LED

LED原理图

单个led 常亮/闪烁

PD2锁存器控制LED的打开关闭

573锁存器:PD2高电平使能锁存器,可以 保留D1~D8八个引脚的状态(只有在锁存器使能情况下才保存);并且让Q1~Q8一直输出此状态(无论使能锁存器还是不使能锁存器,都输出原先的状态)

新建文件存LED.c 和 LED.h文件

在LED.h文件中——防止头文件main.c 被重复编译

#ifndef __LED_H
#define __LED_H

#include "main.h"

void LED_Control(uint8_t ledcter);

#endif//内容都写在里面

在LED.c文件 #include “LED.h”

User文件夹中添加一下新建文件

  • Src文件夹 存.c 文件
  • Inc文件夹 存.h 文件

在led.c中写函数void

void LED_Control(uint8_t ledctrl)
{
	HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);//先关闭led的引脚
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	
	HAL_GPIO_WritePin(GPIOC,ledctrl<<8,GPIO_PIN_RESET);//1111 1111 0000 0000
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
    //
	
}

在.h文件也要声明函数名

在mian.c函数中

  1. 在user~~include中 声明 LED的.h头文件

  2. 在user code begin pv新建定义参数 +使用led的函数

  3. 在主循环while中 声明使用led函数

  4. /* USER CODE BEGIN PV */
    uint8_t ledctrl = 0;
    uint32_t ledTick = 0;
    void LED_Process(void)
    {
    	if(uwTick - ledTick < 100) return;
    	ledTick = uwTick;
    	ledctrl ^= 0x01;     //这个变量为滴答定时器
    	LED_Control(ledctrl);
    }
    
    
    闪灯要定义 32位大小的参数 
    
    ### 单向流水灯
    
    运用
    
    ```cpp
    /* USER CODE BEGIN PV */
    uint8_t ledcnt_100ms = 0;
    uint8_t ledFlag = 0;//标志位
    void SysTick_Handler(void)  //1ms
    {
       //运用中断函数
      HAL_IncTick();
      ledcnt_100ms++;
    	if(100 == ledcnt_100ms)
    	{
    		ledFlag = 1;
    		ledcnt_100ms = 0;
    	}
    }
    
    void LED_Process(void)
    {
        if(1 == ledFlag)
    	{
    		static uint8_t ledState = 1;
    		//静态化赋值 相当于初始化一次,之后的值也是它
    		//初始化ledState==1;
    		//进入case 1;ledState==2,break跳出Switch之后
    		//ledState==2再进入case 2   以此类推
    		ledFlag = 0;           
    		switch(ledState)
    		{
    			case 1:
    			{
    				LED_Control(0x01);ledState = 2;break;				
    			}
    			case 2:
    			{
    				LED_Control(0x02);ledState = 3;break;
    			}
    			case 3:
    			{
    				LED_Control(0x04);ledState = 4;break;
    			}
    			case 4:
    			{
    				LED_Control(0x08);ledState = 5;break;
    			}
    			case 5:
    			{
    				LED_Control(0x10);ledState = 6;break;
    			}
    			case 6:
    			{
    				LED_Control(0x20);ledState = 7;break;
    			}
    			case 7:
    			{
    				LED_Control(0x40);ledState = 8;break;
    			}
    			case 8:
    			{
    				LED_Control(0x80);ledState = 1;break;
    			}
    			//0x01--0x80 十六进制转化为二进制
    	    }
         }
    }//最后在main函数中 while{}内声明LED_Process( );
    /*=============================用嘀嗒时钟=============================*/
    uint32_t ledTick = 0;
    void LED_Process(void)
    {
    	if(uwTick - ledTick < 200)  return;
    	ledTick = uwTick;
    	static uint8_t ledState = 1;
    	
    	if(1 == ledFlag)
    	{
    		ledFlag = 0;           
    		switch(ledState)
    		{
    			case 1:
    			{
    				LED_Control(0x01);ledState = 2;break;				
    			}
    			case 2:
    			{
    				LED_Control(0x02);ledState = 3;break;
    			}
    			case 3:
    			{
    				LED_Control(0x04);ledState = 4;break;
    			}
    			case 4:
    			{
    				LED_Control(0x08);ledState = 5;break;
    			}
    			case 5:
    			{
    				LED_Control(0x10);ledState = 6;break;
    			}
    			case 6:
    			{
    				LED_Control(0x20);ledState = 7;break;
    			}
    			case 7:
    			{
    				LED_Control(0x40);ledState = 8;break;
    			}
    			case 8:
    			{
    				LED_Control(0x80);ledState = 1;break;
    			}
    			//0x01--0x80 十六进制转化为二进制
    	 }
    	}
    }
    
        
        

KEY

key的原理图

定时器

定时器的概念、

PWM 3种模式
PWM模式: 同一定时器中,不同的通道下,输出的频率固定,占空比可变
PWM输出比较模式: 同一定时器下,不同通道能够产生频率不同,占空比不同,甚至相位也不同的方波
PWM捕获模式: PWM比较模式是输出不同频率或者占空比,这个是捕获就是反过来已知波形图而去计算对应占空比和频率
名词 描述
PWM 脉冲宽度调制,对模拟电路进行控制,应用于电机的控制、灯光的亮度调节、功率控制等
周期 一个完整PWM波形所持续的时间
占空比 有效电平持续时间(Ton)与周期时间(Period)的比值
方波 跟占空比差不多,一般用百分数表示,占空比0.5就是方波50%
PWM频率 是指每秒钟信号从高电平到低电平再回到高电平的次数
定时器 用途
TIM1、TIM8 高级定时器:具有通用功能以外、还具有死区控制的互补信号输出、紧急刹车关断输入等功能
TIM6、TIM7 基础定时器:定时、计数功能
其余 通用计时器:具备多路独立的捕获和比较通道,可以完成定时/计数、输入捕获、输出比较等功能。
计算公式
占空比计算公式:Duty = (Ton / Period)× 100%
period = (计数值 + 1)× (分频 + 1)/ 时钟频率
Duty = (正周期时间 / (总计数值 + 1 ))× 100%
  1. tim6 和 tim7是基础定时器——定时、计数功能

    在CubeMX中记得开启定时器

    √ Activated 【NVIC Settings】 √ Enable

//例如:每过100ms获取一次时间
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint16_t Time_10ms_count = 0;
	
	if(htim == &htim6)
	{
		Time_10ms_count++;
		
		if(100 == Time_10ms_count)
		{
			Time_10ms_count = 0;
			LCD_display_function();//显示函数
		}
    }
}
  1. TIM-IC捕获

    测频率支路设置成 直接捕获模式 ,而测脉宽的支路设置成 间接模式

书写细节

模块化

  1. 新建一个 .h文件 存放(#include ~~)类函数。 其他文件只需要#include “此文件名” 就好了

    #include “string.h” //c语言三件套
    #include “stdio.h”
    #include “stdlib.h”

  2. 写函数分区更明朗

  3. 在main.c 中声明函数要带extern (减少报错,可有可无,我的程序需要)

    例如:extern void Hardware_Init(void);

  4. 被调用的函数要放在前面写 才能被调用成功,因为调用函数是从上往下调用

    例如

    void  beitiaoyong(void);
    
    void tiaoyong(void)
    {
        beitiaoyong(void);
    }	

原理图怎么看

R(电阻) C(电容—隔直通交) L(电感—隔交通直)U(集成块)

芯片:GND(地)VCC(电源)AVDD、DVDD

跳线帽:起控制使能的作用。相当于一个开关,拔掉相当于断开开关