蓝桥杯嵌入式代码
更新日记
4.5 添加读取adc函数 给出pwm配置建议及快速操作 给出定时器计算公式
4.7 更新&&改正eeprom错误
文章目录
一、LED模块
SN74HC573为锁存器芯片
LE为锁存使能 低电平锁存输出状态不变
输出有效且未锁存的状态 输入等于输出
根据电路来看输出等于输入为低电平的时候led灯亮
void led_disp(uint8_t ledmark)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//解除锁存状态
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);//熄灭led
HAL_GPIO_WritePin(GPIOC,ledmark<<8,GPIO_PIN_RESET);//GPIO为16位 高八位对应led 左移八位操作led
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//锁存
}
二、按键
作者电路分析不是很好 就不分析了学会再回来补上
江科大yyds
按键未按下时IO口读到高电平
按键按下IO口读取到低电平
1.阻塞式按键
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0;
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0)//只给出一个按键其余自己写就是换个引脚
{
HAL_Delay(20);
while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0);
HAL_Delay(20);
KeyNum = 1;
}
return KeyNum;
}
2.非阻塞式按键(单击,双击,长按)基于江科大非阻塞式按键
按键判断优先级 长按>双击>单击
看着长分为四部分 传递函数 状态函数 判断函数 计时函数
说一下最长的判断函数分为两小部分 每二十秒读取状态 判断是否长按 然后再判断是否双击
key.c
#include "main.h"
#include "gpio.h"
#include "key.h"
uint8_t KeyNum,is_first,is_long_press;
uint16_t double_click,press_time,long_press_time=50;
uint8_t Key_GetNum(void)//向外界传递按键值
{
uint8_t temp;
if(KeyNum)
{
temp=KeyNum;
KeyNum=0;
return temp;
}
return 0;
}
uint8_t Key_GetState(void)//读取按键状态
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
{
return 4;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
{
return 1;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
{
return 2;
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
{
return 3;
}return 0;
}
void Key_Kick(void)
{
static uint8_t i;//切记static一定要加
static uint8_t past,now;
i++;
if (i >= 20) {
i = 0;
past = now;
now = Key_GetState();
// 长按检测逻辑
if (past == now && now != 0) {
press_time++;
if (press_time >= long_press_time ) {
KeyNum = now + 5; // 长按事件编码(1→6, 2→7, 3→8, 4→9)
is_long_press = 1;
press_time = 0;
}
} else {
press_time = 0;
}
//长按松手或短按
if (past != 0 && now == 0) {
//如果不是松手
if(!is_long_press){
if (is_first) {
is_first = 0;
double_click = 0;
KeyNum = 5; // 双击事件
} else {
KeyNum = past; // 短按事件
is_first = 1;
double_click = 0;
}
}
//清除标志位防止程序无法进入短按
is_long_press=0;
}
}
}
void Key_HandleDoubleClickTimer(void)//此函数用于计算双击间隔时间
{
// 双击计时
if (is_first)
{
double_click++;
if (double_click >= 300)//超过300ms则不是双击
{
is_first = 0;
double_click = 0;
}
}
}
三 、LCD
LCD引脚和LED引脚有所重复 更改LCD前记得锁存
直接移植官方文件即可
char text[20];
sprintf(text," KEY=%d ",Keynum);//将KEY=%d打印到text数组中
LCD_DisplayStringLine(Line1,(uint8_t *)text);
//在第二行显示text
//Line0才是真正意义上的第一行
四、定时器
定时器详解
我直接给公式和代码了
stm32cubemx操作:使能,开中断,配置参数
1、基本计时功能
T=(psc+1)*(arr+1)/80000000 单位s
HAL_TIM_Base_Start_IT(&htim6);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//代码
Key_Kick();
Key_HandleDoubleClickTimer();
}
2、ADC
//一次启动得到一次数据 持续捕获需放入循环
//HAL_ADC_Start(&hadc1);
//HAL_ADC_Start(&hadc2);
//adc2=HAL_ADC_GetValue(&hadc1)*3.3/4095;
//adc1=HAL_ADC_GetValue(&hadc2)*3.3/4095;
float adc_read(ADC_HandleTypeDef *hadc)
{
HAL_ADC_Start(hadc);
uint32_t Value=HAL_ADC_GetValue(hadc);
return 3.3f*Value/4096;
}
3、PWM
建议PSC为799 ARR为99
这时频率为1khz
PSC缩小为399 频率为2khz
PSC缩小为199 频率为4khz以此类推
CCR为多少占空比为多少
// 启动PWM
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
// 设置占空比(50% duty)
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, htim2.Instance->ARR / 2);
__HAL_TIM_SET_PRESCALER(&htim2,800);
快速设置
TIMx->CNT=
TIMx->ARRx= 通道几就是arr几
TIMx->PSC=
//f=80000000/(psc+1)*(arr+1)
//duty=ccr/arr+1
4、输入捕获
// 启动输入捕获
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
// 输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&htim3))
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
{
com1=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
com2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
__HAL_TIM_SetCounter(htim,0);
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
}
}
}
while(1)
{
//计算函数放在主循环
fre=80000000/80/com1;
duty=(com2/com1)*100;
}
五、串口
HAL_UART_Receive_IT(&huart1,&rxdat,1);
int fputc(int ch, FILE *f)//重定向
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
Rxdata[pt++]=rxdat;
if(rxdat==1)
{
led_mark|=0x08;
}
else
{
led_mark &= ~0x08;
}
HAL_UART_Receive_IT(&huart1,&rxdat,1);//重复开启
}
}
六、I2C 读取eeprom
官方给的I2C
一定记得初始化PB6 PB7 GPIO_Output
void eeprom_Write(uint8_t addr,uint8_t data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
HAL_Delay(10);
}
uint8_t eeprom_Read(uint8_t addr)
{
uint8_t data;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
data=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return data;
}