问题:
ADC输入输出初始化设定?
各外设的初始化设定?
初始化设定:
1.内部测量R37输出信号 ADC PB15 ADC_IN
2.PA1 频率测量 pwm TIM2_CH2 pwm输入捕获模式 配置基础分频,溢出max值(0xffff),使能NVIC中断
3.PA7 脉冲输出 pwm TIM17_CH1 pwm输出 generation 配置基础分频 初始周期频率 初始高电平时间(占空比)无需NVIC中断配置
4.按键 GPIO input 其余默认
5.LCD已配置 记得函数加驱动
6.LED PD2作推挽输出 GPIO_OUT
初始化细节:
1.Project Manager 选 v5,code generator 选第二项+产生.c.h文件
2.加入 lcd.c + include.h 文件
3.初始化完成后,复制一份作模板,用于配置cube,后续再移植到原工程里
4.每完成一个模块,建议压缩一份工程文件,备用
编程细节:
1.模块函数在 /* USER CODE BEGIN 0 */ 分块编写,可防止代码被覆盖更改
2.调用函数的头文件相关
3.注意题目要求,显示函数 需要空多少格,显示多少位,显示位数相关表达?(小数表达?)
4.写if必想else 用else尽量谨慎 用else if列出各种情况更保险
5.加减函数,注意其范围限定,用if 或 取余%
6.界面切换最好优先清屏,防止残留:LCD_Clear(Black);
7.如何编写?:display_mode = (display_mode + 1) % 3;//+1为切换下一个模式,%3为保证只有0—2三个模式
8.LCD显示,注意不同长度数据的覆盖问题 可添加空格?相关知识点?
9.LED功能放置到最后执行
10.volt_37 < 1.0f 运算比较 需为同一数据类型
报错经验:
1.Undefined symbol Key_Read (referred from main.o).——>未定义,看是否include.h,工程文件是否已添加.c
模块化编程
1.LCD显示
0)优先问:添加.c.h了吗?初始化了吗?移植驱动了吗?开启模块了吗?
1)宏定义显示界面变量
2)display_mode变量 代替界面 用于切换
3)设定显示数组:u8 display_buf[20];
4)设定界面参数:u16 freq,float vol_r37,注意题目要求的初始化条件
5)注意显示函数空位 格式 位数要求
6)编写LCD_Process(); 显示函数相关:
//组合使用,先sprintf至buf中,再显示
sprintf((char*)display_buf," FRQ:%5dHZ",freq_pa1);
LCD_DisplayStringLine(Line3, (unsigned char *)display_buf);
7)不同界面,用 if...else if...
2.按键控制
1)自行编写key.c.h文件 并include
/*key.c*/
#include "key.h"
#include "lcd.h"
#define KB1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define KB2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define KB3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define KB4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
#define KEYPORT KB1 | (KB2<<1) | (KB3<<2) | (KB4<<3) | 0xf0
u8 Trg; // 全局变量,单次触发
u8 Cont; // 全局变量,长按
void Key_Read(void)
{
u8 ReadData = (KEYPORT)^0xff; // 1
Trg = ReadData & (ReadData ^ Cont); // 2
Cont = ReadData; // 3
}
/*key.h*/
#ifndef __KEY_H
#define __KEY_H
#include "main.h"
extern u8 Trg; // 全局变量,单次触发
extern u8 Cont; // 全局变量,长按
void Key_Read(void);//在附属.c文件创建的函数一定要在头文件中声明
#endif
2)注意题目逻辑,是切换到某个界面之后,该按键按下才有反应,所以需优先if判断是否为相应界面
3.ADC采集
1)确认已经初始化后,直接编写ADC采集函数,while执行即可
//3.ADC采集
u16 adc2_val;
void ADC_Process()
{
HAL_ADC_Start(&hadc2);
adc2_val = HAL_ADC_GetValue(&hadc2);
volt_r37 = adc2_val / 4096.0f * 3.3f;
}
4.PWM捕获
1)调用回调函数 HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
知识点:PWM捕获的回调函数在哪?
stm32g4xx_it.c——找到并跳转HAL_TIM_IRQHandler(&htim2);——往下几行找到 HAL_TIM_IC_CaptureCallback(htim);——跳转即为其弱定义函数
2)回调函数内:
1.获取周期CNT(us)
2.重新设置计数器
3.计算频率并赋值
4.重新开启中断,注意main初始化部分也要开
//4.PWM捕获
u32 tim2_cnt = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
tim2_cnt = __HAL_TIM_GetCounter(&htim2);
__HAL_TIM_SetCounter(&htim2,0);//计数器重新开始计数,下一周期
freq_pa1 = 1000000 / tim2_cnt; //求频率 Hz
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);//记得最后要重新开启中断
}
3)main函数中记得初始化 开启该TIM中断: HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
5.PWM输出
1)main初始化开启PWM输出:HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
2)PWM输出函数,主要操作寄存器,ARR为总时间(对应频率),CCRx为高电平时间(对应占空比),函数根据题意设定:
void PWM_Process()
{
TIM17 -> ARR = tim2_cnt * R_div;//此为操作寄存器周期 时间
TIM17 -> CCR1 = tim2_cnt * R_div /(3.3f/volt_r37);// 将高电平时间根据电压来分频,细品,代入首位特值分析
}
实际操作:如何观察PWM波?
PWM输出用示波器看
PWM输入捕获,用捕获引脚接入555定时器的跳帽下引脚,具体看数据手册,注意,输入捕获求频率需接到R39\R40信号发生器方可调整其发生信号频率