目录
一、adc
原理图编辑引脚配置
Adc通道使能配置
实例测试
编辑效果显示
案例程序
badc
按键相关函数
测量频率+占空比
main
按键的过程
显示界面的过程
二、IIC通信-eeprom
原理图AT24C02
引脚配置
不可用状态,用的软件IIC
官方库移植
At24c02手册
编辑真题案例
编辑实验现象
案例程序
i2c.c
读的函数
写的函数
main
主函数
按键的过程、参数显示界面
案例显现展示
三、uart
原理图
官方给的代码的测试现象
cube配置
参数设置
波特率设置
编辑中断使能
案例代码呈现
main
主函数
按键设置及界面显示
现象效果展示
一、adc
原理图引脚配置
Adc通道使能配置
Adc是将一个模拟的值Adc通道使能配置
转化为一个电压的值
ADC2通道使能及模式设置
之后点击生成即可
实例测试
效果显示
显示在第三行
案例程序
badc
/----------------------------badc.h---------------------------------------------/
#ifndef __BADC_H__
#define __BADC_H__#include "main.h"
double getADC(ADC_HandleTypeDef *pin);#endif
/-----------------------------badc.c---------------------------------------------/
#include "badc.h"//读取adc值的函数double getADC(ADC_HandleTypeDef *pin)
{uint adc;//读出的原始值HAL_ADC_Start(pin);//开启adcadc = HAL_ADC_GetValue(pin);return adc*3.3/4096;// 读取到的电压值,均分一个等分看在3.3所占的比例
}
/---------------------------------interrupt.h----------------------------------/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__#include "main.h"
#include "stdbool.h"
struct keys
{uchar judge_sta;bool key_sta;bool single_flag;//确认被按下他为1uint key_time; //判断按下的时间,时间比较长uchar long_flag;
};void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);#endif
/---------------------------------interrupt.c----------------------------------/
按键相关函数
struct keys key[4] = {0,0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM4){key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);for(int i = 0;i<4;i++){switch (key[i].judge_sta){case 0:{if(key[i].key_sta == 0) //发现按键被按下{ key[i].judge_sta=1;key[i].key_time=0;//将时间清零}}break;case 1:{if(key[i].key_sta ==0)//消抖的过程里面就不能确定他短按键会与长按键冲突{key[i].judge_sta=2;}else key[i].judge_sta=0;}break;case 2:{if(key[i].key_sta==1)//长按{key[i].judge_sta=0; if(key[i].key_time<70){key[i].single_flag = 1;}}else{key[i].key_time++;//在他没有松开的打断时间内if(key[i].key_time>70) key[i].long_flag=1;}}break;case 3:{}break;}}}
}
测量频率+占空比
double ccrl_val1a = 0,ccrl_val2a = 0;
uint ccr1_val1b=0,ccr1_val2b=0;
uint frq1=0,frq2=0; //频率
float duty1=0,duty2=0;//占空比void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM2){if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//中段消息来源 选择直接输入的通道{ccrl_val1a= HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1); //计时值hal库的计时函数 直接ccr1_val1b= HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); //计时值hal库的计时函数 间接__HAL_TIM_SetCounter(htim,0);//计时值清零frq1=(80000000/80)/ccrl_val1a;//计算频率duty1=(ccr1_val1b/ccrl_val1a)*100;HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);//从小打开定时器HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);//从小打开定时器}}if(htim->Instance==TIM3){if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//中段消息来源 选择直接输入的通道{ccrl_val2a= HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1); //计时值hal库的计时函数 直接ccr1_val2b= HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); //计时值hal库的计时函数 间接__HAL_TIM_SetCounter(htim,0);//计时值清零frq2=(80000000/80)/ccrl_val2a;//计算频率duty2=(ccr1_val2b/ccrl_val2a)*100;HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);//从小打开定时器HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);//从小打开定时器}}
}
main.h
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "interrupt.h"
#include "badc.h"
/* USER CODE END Includes *//* USER CODE BEGIN PTD */
void key_proc(void);//按键的过程
void disp_proc(void);//显示界面的过程extern struct keys key[];
extern uint frq1,frq2;//计算的到的回调值
extern float duty1,duty2;
uchar view=0;uchar pa6_duty = 10;
uchar pa7_duty = 10;/* USER CODE END PTD */
main
int main(void)
{/* USER CODE BEGIN 2 */LED_Disp(0x00);//LED初始化LCD_Init();//LCD初始化LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);HAL_TIM_Base_Start_IT(&htim4); //定时器中断HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//打开pwm的输出通道HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//打开pwm的输通道//打开定时器HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //定时器中断 频率测量捕获定时器开启HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); //定时器中断/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */key_proc();disp_proc();
// LED_Disp(0x02);
// HAL_Delay(500);
// LED_Disp(0x00);
// HAL_Delay(1000);}/* USER CODE END 3 */
}
按键的过程
/* USER CODE BEGIN 4 */void key_proc(void)//按键的过程
{if(key[0].single_flag ==1){view=!view;key[0].single_flag=0;}if(key[1].single_flag ==1)//按键2按下一次加10%{pa6_duty+=10;if(pa6_duty>=100) pa6_duty=10;__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);//设置比较key[1].single_flag=0;}if(key[2].single_flag ==1)//按键3 按下一次加10%{pa7_duty+=10;if(pa7_duty>=100) pa7_duty=10;__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);//设置比较key[2].single_flag=0;}
}
显示界面的过程
void disp_proc(void)//显示界面的过程
{if(view==0){char text[30];sprintf(text," Data ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," FRQ1=%d ",frq1);LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," duty1=%.3f ",duty1);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," FRQ2=%d ",frq2);LCD_DisplayStringLine(Line4, (uint8_t *)text);sprintf(text," duty2=%.3f ",duty2);LCD_DisplayStringLine(Line5, (uint8_t *)text);//ADC显示 1 测量的是靠左的电位器sprintf(text," V:=%.2f ",getADC(&hadc1));//在mx中配置了LCD_DisplayStringLine(Line6, (uint8_t *)text);//2sprintf(text," V:=%.2f ",getADC(&hadc2));//在mx中配置了LCD_DisplayStringLine(Line7, (uint8_t *)text);}if(view==1)//参数显示界面{char text[30];sprintf(text," Para ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," PA6:%d ",pa6_duty);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," PA7:%d ",pa7_duty);LCD_DisplayStringLine(Line4, (uint8_t *)text);//界面清理 sprintf(text," ");LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," ");LCD_DisplayStringLine(Line5, (uint8_t *)text);}
}/* USER CODE END 4 */
二、IIC通信-eeprom
原理图AT24C02
引脚配置
为什么要配置成output模式因为官方会提供一个i2c的库,可以直接用用的是软件IIC
不可用状态,用的软件IIC
之后直接生成就可
官方库移植
将这两个文件复制到bsp文件下面
At24c02手册
1k,2k是容量
一个总线上可以挂很多很多芯片
真题案例
实验现象
问题 ---按键没有用只显示1038
案例程序
#include "i2c - hal.h"官方给的参考程序的头文件有问题所以要改成这样
I2c.h
#ifndef __I2C_H
#define __I2C_H#include "main.h"void I2CStart(void);
void I2CStop(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void I2CInit(void);
void eeprom_write(uchar addr,uchar dat);
uchar eeprom_read(uchar addr);#endif
i2c.c
读的函数
//读的函数uchar eeprom_read(uchar addr)
{//正常代码
// uchar dat;
// I2CStart();//i2c开启
// I2CSendByte(0xa0);//联系芯片
// I2CWaitAck();
// I2CSendByte(addr);//传递的参数
// I2CWaitAck();
//
// //将真实的数据读回
// I2CStart();
// I2CSendByte(0xa1);
// I2CWaitAck();//发送完等待
// dat=I2CReceiveByte();
// I2CSendNotAck();
// I2CStop();
// return dat;//返回结果uchar dat;I2CStart();//i2c开启I2CSendByte(0xa0);//联系芯片 I2CWaitAck();I2CSendByte(addr);//传递的参数I2CWaitAck();I2CStop();I2CStart();//i2c开启I2CSendByte(0xa1);//联系芯片 I2CWaitAck();dat=I2CReceiveByte();I2CSendNotAck();I2CStop();return dat;//返回结果}
写的函数
void eeprom_write(uchar addr,uchar dat)
{I2CStart();//i2c开启I2CSendByte(0xa0);//联系芯片 I2CWaitAck();//等待应答I2CSendByte(addr);//传递的参数I2CWaitAck();I2CSendByte(dat);//数据发送给芯片I2CWaitAck();I2CStop();
}
main
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "interrupt.h"
#include "badc.h"
#include "i2c - hal.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
void key_proc(void);//按键的过程
void disp_proc(void);//显示界面的过程extern struct keys key[];
extern uint frq1,frq2;//计算的到的回调值
extern float duty1,duty2;
uchar view=0;uchar pa6_duty = 10;
uchar pa7_duty = 10;/* USER CODE END PTD */
主函数
int main(void)
{
/* USER CODE BEGIN 2 */LED_Disp(0x00);//LED初始化LCD_Init();//LCD初始化LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);HAL_TIM_Base_Start_IT(&htim4); //定时器中断HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//打开pwm的输出通道HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//打开pwm的输通道//打开定时器HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //定时器中断 频率测量捕获定时器开启HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); //定时器中断/* USER CODE END 2 *//* USER CODE BEGIN WHILE */while (1){/* USER CODE BEGIN 3 */key_proc();disp_proc();
// LED_Disp(0x02);
// HAL_Delay(500);
// LED_Disp(0x00);
// HAL_Delay(1000);}/* USER CODE END 3 */
}
按键的过程、参数显示界面
/* USER CODE BEGIN 4 */void key_proc(void)//按键的过程
{if(key[0].single_flag ==1){view=!view;key[0].single_flag=0;}if(key[1].single_flag ==1)//按键2按下一次加10%{pa6_duty+=10;if(pa6_duty>=100) pa6_duty=10;__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);//设置比较key[1].single_flag=0;}if(key[2].single_flag ==1)//按键3 按下一次加10%{pa7_duty+=10;if(pa7_duty>=100) pa7_duty=10;__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);//设置比较key[2].single_flag=0;}//显示按键频率 eeprom只能存一个8位,所以要将他拆成高八位和低八位if(key[3].single_flag ==1)//按键3{uchar frq_h = frq1 >> 8;uchar frq_l = frq1 & 0xff;eeprom_write(1,frq_h);//写入高位HAL_Delay(10);//太快会发不出去eeprom_write(2,frq_l);//写入低8位key[3].single_flag = 0;}
}void disp_proc(void)//显示界面的过程
{if(view==0){char text[30];sprintf(text," Data ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," FRQ1=%d ",frq1);LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," duty1=%.3f ",duty1);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," FRQ2=%d ",frq2);LCD_DisplayStringLine(Line4, (uint8_t *)text);sprintf(text," duty2=%.3f ",duty2);LCD_DisplayStringLine(Line5, (uint8_t *)text);//ADC显示 1 测量的是靠左的电位器sprintf(text," V:=%.2f ",getADC(&hadc1));//在mx中配置了LCD_DisplayStringLine(Line6, (uint8_t *)text);//2sprintf(text," V:=%.2f ",getADC(&hadc2));//在mx中配置了LCD_DisplayStringLine(Line7, (uint8_t *)text);uint eep_temp=(eeprom_read(1)<<8)+eeprom_read(2);//读取数据,高8位放第1位,低8位放2为sprintf(text," FRQ_eep=%d ",eep_temp);//将存入的数据显示出来LCD_DisplayStringLine(Line8, (uint8_t *)text);}if(view==1)//参数显示界面{char text[30];sprintf(text," Para ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," PA6:%d ",pa6_duty);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," PA7:%d ",pa7_duty);LCD_DisplayStringLine(Line4, (uint8_t *)text);//界面清理 sprintf(text," ");LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," ");LCD_DisplayStringLine(Line5, (uint8_t *)text);}
}/* USER CODE END 4 */
案例显现展示
三、uart
原理图
2022年1月~2月购买的可能会有硬件故障 --
官方给的代码的测试现象
cube配置
改为异步模式,同步模式其他端口被占用,串口参数设置,如果没有设置lcd的话他会默认PC4和PC5,所以需要手动更改
参数设置
波特率设置
根据题目要求设置
中断使能
之后生成代码即可
案例代码呈现
interrupt同上
main
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "interrupt.h"
#include "badc.h"
#include "i2c - hal.h"
#include "string.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
void key_proc(void);//按键的过程
void disp_proc(void);//显示界面的过程extern struct keys key[];
extern uint frq1,frq2;//计算的到的回调值
extern float duty1,duty2;
uchar view=0;uchar pa6_duty = 10;
uchar pa7_duty = 10;/* USER CODE END PTD */
主函数
int main(void)
{/* USER CODE BEGIN 2 */LED_Disp(0x00);//LED初始化LCD_Init();//LCD初始化LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);HAL_TIM_Base_Start_IT(&htim4); //定时器中断HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//打开pwm的输出通道HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//打开pwm的输通道//打开定时器HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //定时器中断 频率测量捕获定时器开启HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); //定时器中断/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */key_proc();disp_proc();//简单的发送char temp[20];sprintf(temp,"frq=%d\r\n",frq1); //打印频率再电脑HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);HAL_Delay(500);}/* USER CODE END 3 */
}
按键设置及界面显示
/* USER CODE BEGIN 4 */void key_proc(void)//按键的过程
{if(key[0].single_flag ==1){view=!view;key[0].single_flag=0;}if(key[1].single_flag ==1)//按键2按下一次加10%{pa6_duty+=10;if(pa6_duty>=100) pa6_duty=10;__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);//设置比较key[1].single_flag=0;}if(key[2].single_flag ==1)//按键3 按下一次加10%{pa7_duty+=10;if(pa7_duty>=100) pa7_duty=10;__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);//设置比较key[2].single_flag=0;}//显示按键频率 eeprom只能存一个8位,所以要将他拆成高八位和低八位if(key[3].single_flag ==1)//按键3{uchar frq_h = frq1 >> 8;uchar frq_l = frq1 & 0xff;eeprom_write(1,frq_h);//写入高位HAL_Delay(10);//太快会发不出去eeprom_write(2,frq_l);//写入低8位key[3].single_flag = 0;}
}void disp_proc(void)//显示界面的过程
{if(view==0){char text[30];sprintf(text," Data ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," FRQ1=%d ",frq1);LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," duty1=%.3f ",duty1);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," FRQ2=%d ",frq2);LCD_DisplayStringLine(Line4, (uint8_t *)text);sprintf(text," duty2=%.3f ",duty2);LCD_DisplayStringLine(Line5, (uint8_t *)text);//ADC显示 1 测量的是靠左的电位器sprintf(text," V:=%.2f ",getADC(&hadc1));//在mx中配置了LCD_DisplayStringLine(Line6, (uint8_t *)text);//2sprintf(text," V:=%.2f ",getADC(&hadc2));//在mx中配置了LCD_DisplayStringLine(Line7, (uint8_t *)text);串口相关代码///uint eep_temp=(eeprom_read(1)<<8)+eeprom_read(2);//读取数据,高8位放第1位,低8位放2为sprintf(text," FRQ_eep=%d ",eep_temp);//将存入的数据显示出来LCD_DisplayStringLine(Line8, (uint8_t *)text);}if(view==1)//参数显示界面{char text[30];sprintf(text," Para ");LCD_DisplayStringLine(Line1, (uint8_t *)text);sprintf(text," PA6:%d ",pa6_duty);LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text," PA7:%d ",pa7_duty);LCD_DisplayStringLine(Line4, (uint8_t *)text);//界面清理 sprintf(text," ");LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text," ");LCD_DisplayStringLine(Line5, (uint8_t *)text);}
}/* USER CODE END 4 */
现象效果展示
串口数据
lcd显示