蓝桥杯嵌入式速成

news2025/9/20 2:29:15

蓝桥杯嵌入式速成

  • cubmx创建工程
  • 利用官方提供的LCD代码创建工程(15届不能用)
  • 利用官方提供的LCD代码创建工程(15届能用)
  • Keil配置
    • 头文件注意
    • 其他注意
  • LED
    • 闪烁
  • 按键
    • 短按
    • 长按
    • 双击
  • LCD
    • 高亮行
    • 高亮字符
  • RTC
  • ADC
  • I2C
  • uart
    • 接收
    • 发送
  • PWM
  • DAC
  • 定时器
  • 捕获PWM频率+占空比
  • 占空比

cubmx创建工程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

利用官方提供的LCD代码创建工程(15届不能用)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

利用官方提供的LCD代码创建工程(15届能用)

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Keil配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

头文件注意

在这里插入图片描述

使用sprintf需要加头文件stdio.h
使用memset需要加头文件string.h

其他注意

如果要在main使用需要extern
uwTick 1ms加一次

Led 需要用LedDisp(0)初始化
串口接收初始化HAL_UART_Receive_IT(&huart1,&rx_data,1);
串口不工作看中断是不是打开,引脚是不是PA9,PA10
PWM初始化HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
输入捕获初始化HAL_TIM_IC_Start_IT(&htim16, TIM_CHANNEL_1);;
I2C 需要用I2CInit()初始化
EEP开始需要第一次先写入题目要求的合法数据 之后再读
EEP 写0xa0 读(先写要读的地址) 0xa1
mcp 写0x5e0x5f

在这里插入图片描述

LED

在这里插入图片描述
Led初始化LedDisp(0)


void LED_disp(u8 led)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //打开锁存器
	HAL_GPIO_WritePin(GPIOC,0xFF00,GPIO_PIN_SET);	// set熄灭
	HAL_GPIO_WritePin(GPIOC,led<<8,GPIO_PIN_RESET);	// reset点亮
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //关闭锁存器
}



vu32 ledTick = 0;
u8 led = 0;
void LED_proc()
{
	if(uwTick - ledTick  < 100) return;	
	ledTick = uwTick;
	
	LED_disp(led);
}

闪烁

在这里插入图片描述

按键

在这里插入图片描述
在这里插入图片描述

u8 ko,kv,ku,kd = 0;

void KeyRead()
{
  //5行四个按键
  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 0) kv = 1;
  else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 0) kv = 2;
  else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == 0) kv = 3;
  else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0) kv = 4;
  else kv = 0;// 默认给值为0,这里别忘记了
  
  kd = kv &(ko ^ kv);
  ku = ~kv &(ko ^ kv);
  ko = kv;  
}

短按

vu32 keyTick = 0;
void KeyProc()
{
  if(uwTick - keyTick < 20) return;
  keyTick =uwTick;
  
  KeyRead();
  if(kd == 1)
  {
  }
  else if(kd == 2)
  {
  }
  else if(kd == 3)
  {
  }
  else if(kd == 4)
  {
  }

长按

vu32 keyTick = 0;
vu32 keyLongTick = 0;
void KeyProc()
{
  if(uwTick - keyTick < 20) return;
  keyTick = uwTick;
  
  KeyRead();
  
  if(ku == 1) //注意用ku
  {
	//短按
  }
  else if(ku == 2 && (uwTick - keyLongTick < 800)) 
  {
  	//短按
	//注意要防止长按抬手触发短按多加了一个判断条件
  }
  else if(ku == 3 && (uwTick - keyLongTick < 800))
  {
  } 
  else if(ku == 4 && (uwTick - keyLongTick < 800))
  {
  }
  else if(kd == 2 || kd == 3 || kd == 4)
  {
  	//开始长按计时
    keyLongTick = uwTick;
  }
  
  if(kv == 2 && (uwTick - keyLongTick > 800))
  {
    //长按操作
  }
  
  if(kv == 3 && (uwTick - keyLongTick > 800))
  {
	//长按操作
  }
  
  if(kv == 4 && (uwTick - keyLongTick > 800))
  {
    //长按操作
  }
  
}

双击


u8 keyStatus;
u32 keyTick;
u32 keyIdle = 0;
u32 doubleTick = 0;
void Key_proc()
{
	if(uwTick - key_tick < 20) return;
	key_tick = uwTick;

	KEY_read();
	
	keyIdle = uwTick - doubleTick ;//2次按键间隔的时间,单位ms
	//之前没有按下
	if(kd ==  1 && keyStatus == 0)
	{
		keyStatus = 1;
		doubleTick = uwTick;		//按下变为状态1,开始计时
	}
	else if(keyStatus  == 1)
	{
	//如果400ms内再按触发双击,如果第一次按后400ms没按则才触发单击,这里改为300ms也可以,我感觉有点快
		if(keyIdle < 400 && kd == 1)	
		{
			//双击操作
			keyStatus = 0;
		}
		else if(key_idle > 400)
		{
			//单击
			keyStatus= 0;
		}
	}
}

LCD

LCD最多21位

高亮行

if(pwm_line == 0)
	LCD_SetBackColor(Green);
sprintf((char *)lcd_buf,"   PA3_F:%-5dHz     ",pa3_frq);	
LCD_DisplayStringLine(Line2,lcd_buf);
LCD_SetBackColor(Black);
		
if(pwm_line == 1)
	LCD_SetBackColor(Green);
sprintf((char *)lcd_buf,"   PA3_D:%d %%        ",pa3_duty);	
LCD_DisplayStringLine(Line3,lcd_buf);
LCD_SetBackColor(Black);

高亮字符

if(b2wz == 1 ) LCD_SetBackColor(Red);
LCD_DisplayChar(Line4,320-(4 * 16),times[ccwz].h/10+'0');
LCD_DisplayChar(Line4,320-(5 * 16),times[ccwz].h%10+'0');
LCD_SetBackColor(Blue);

LCD_DisplayChar(Line4,320-(6 * 16),':');

 if(b2wz == 2) LCD_SetBackColor(Red);
 LCD_DisplayChar(Line4,320-(8 * 16),times[ccwz].m/10+'0');
 LCD_DisplayChar(Line4,320-(9 * 16),times[ccwz].m%10+'0');
 LCD_SetBackColor(Blue);
 
LCD_DisplayChar(Line4,320-(10 * 16),':');

if(b2wz == 3) LCD_SetBackColor(Red);
LCD_DisplayChar(Line4,320-(12 * 16),times[ccwz].s/10+'0');
LCD_DisplayChar(Line4,320-(13 * 16),times[ccwz].s%10+'0');
LCD_SetBackColor(Blue);

RTC

可以找例程在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

RTC_DateTypeDef D;
RTC_TimeTypeDef T;
u32 rtc_tick = 0;
void RTC_proc()
{
	if(uwTick - rtc_tick < 100)
		rtc_tick = uwTick;
  /* Get the RTC current Time */
  HAL_RTC_GetTime(&hrtc, &T, RTC_FORMAT_BIN);
  /* Get the RTC current Date */
  HAL_RTC_GetDate(&hrtc, &D, RTC_FORMAT_BIN);
}

ADC

在这里插入图片描述
在这里插入图片描述

如果双通道需要配置
在这里插入图片描述
采样时间选最大
在这里插入图片描述

u32 r37_value = 0;
u32 r38_value = 0;
u32 mcp_value = 0;
float r37_volt = 0;
float r38_volt = 0;
float mcp_volt = 0;
u32 adc_tick = 0;
void ADC_proc()
{
	if(uwTick - adc_tick < 100)
		return;
	adc_tick = uwTick;
	//就这两个函数
	HAL_ADC_Start(&hadc1);
	mcp_value = HAL_ADC_GetValue(&hadc1);
	
	HAL_ADC_Start(&hadc1);
	r38_value = HAL_ADC_GetValue(&hadc1);
	
	HAL_ADC_Start(&hadc2);
	r37_value = HAL_ADC_GetValue(&hadc2);
	
	r37_volt = r37_value * 3.3 / 4096.0;
	r38_volt = r38_value * 3.3 / 4096.0;
	mcp_volt = mcp_value * 3.3 / 4096.0;	

}

I2C

I2C 需要用I2CInit初始化

//写9行
void EEpWrite(uint8_t addr,uint8_t data)
{
  I2CStart();
  I2CSendByte(0xa0);
  I2CWaitAck();
  I2CSendByte(addr);
  I2CWaitAck();
  I2CSendByte(data);
  I2CWaitAck();
  I2CStop();
  HAL_Delay(5);
}
//读13行
uint8_t EEpRead(uint8_t add)
{
	uint8_t data;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	data = I2CReceiveByte();
	I2CSendNotAck(); //注意是noack
	I2CStop();
	return data;
}


void MCP_write(uint8_t mcp)
{
	I2CStart();
	I2CSendByte(0x5E);
	I2CWaitAck();
	I2CSendByte(mcp);
	I2CWaitAck();
	I2CStop();
}

uart

在这里插入图片描述

接收

串口接收初始化HAL_UART_Receive_IT(&huart1,&rx_data,1);
接收中断3行

u8 rx_pointer , rx_data;
u8 rx_buff[30];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	rx_tick = uwTick;
	HAL_UART_Receive_IT(&huart1,&rx_data,1);
	rx_buff[rx_pointer++] = rx_data;
}

接收处理

u32 rx_tick = 0;
void RX_proc()
{
	if(uwTick - rx_tick < 50) return;
	rx_tick = uwTick;
	if(rx_pointer == 1 && rx_buff[0] == '#')
	{
		//接收输出正确
	}
	else if(rx_pointer > 0)
	{
		//接收输出错误
	}
	rx_pointer = 0;
	memset(rx_buff,0,sizeof(rx_buff));
}

发送

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
struct __FILE
{
  int handle;
  /* Whatever you require here. If the only file you are using is */
  /* standard output using printf() for debugging, no file handling */
  /* is required. */
};
/* FILE is typedef’d in stdio.h. */
FILE __stdout;
int fputc(int ch, FILE *f) 
{
	HAL_UART_Transmit(&huart1,(u8 *)&ch,1,50);
  /* Your implementation of fputc(). */
  return ch;
}

然后就可以通过printf发送串口数据

PWM

不要用同一个定时器设置不同引脚的PWM
PWM初始化HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);在这里插入图片描述 在这里插入图片描述

u16 pa3_frq = 1000;
u16 pa4_frq = 2000;
u8 pa3_duty = 50;
u8 pa4_duty = 50;
u32 pwm_tick = 0;
void PWM_proc()
{
	if(uwTick - pwm_tick < 100)return;
	pwm_tick = uwTick; 
	
	__HAL_TIM_SetAutoreload(&htim2,1e6 / pa3_frq - 1);
	__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_4,(1e6 / pa3_frq) * pa3_duty / 100);
	
	__HAL_TIM_SetAutoreload(&htim3,1e6 / pa4_frq - 1);
	__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,1e6 / pa4_frq * pa4_duty / 100);
}

DAC

在这里插入图片描述

u16 dac_value = 0;
u32 dac_tick = 0;
void DAC_proc()
{
	if(uwTick - dac_tick < 100) return;
	dac_tick = uwTick;
	HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_R,dac_value);
	HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
}

定时器

定时器先配置定时时间 然后打开中断 然后打开定时器 即可
在这里插入图片描述

捕获PWM频率+占空比

PA15 -> R39
PA4 -> R40
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开列程
在这里插入图片描述
打开输出捕获中断
在这里插入图片描述
我们改成我们需要的
在这里插入图片描述
回调函数也复制过去
在这里插入图片描述
变量也复制过去
在这里插入图片描述
我们有俩个定时器所以要先判断一下
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

占空比

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1584434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++的学习之路:22、多态(1)

摘要 本章主要是说一些多态的开头。 目录 摘要 一、多态的概念 二、多态的定义及实现 2.1、多态的构成条件 2.2、虚函数 2.3、虚函数的重写 2.4、C11 override 和 final 2.5、重载、覆盖(重写)、隐藏(重定义)的对比 三、思维导图 一、多态的概念 多态的概念&#…

ELK 企业级日志分析系统 简单介绍

目录 一 ELK 简介 1&#xff0c; elk 是什么 2&#xff0c;elk 架构图 3&#xff0c;elk 日志处理步骤 二 Elasticsearch 简介 1&#xff0c; Elasticsearch 是什么 2&#xff0c; Elasticsearch 的核心概念 3&#xff0c; Elasticsearch 的原理 三 Logstas…

遥感图像处理:从畸变消除到专题信息提取

​ ​ ​在遥感技术的应用中&#xff0c;图像处理是不可或缺的关键步骤。从消除各种辐射畸变和几何畸变&#xff0c;到利用增强技术突出景物的光谱和空间特征&#xff0c;再到进一步理解、分析和判别处理后的图像&#xff0c;这一过程为我们呈现了一幅幅更为真实、清晰的…

uniapp区分app、h5、小程序

APP端 标签内 <!-- #ifdef APP-PLUS --><view> APP端 </view> <!-- #endif --> JSCSS内 /*#ifdef APP-PLUS*/console.log(APP端) /*#endif*/ H5端 标签内 <!-- #ifdef H5 --><view> H5端 </view> <!-- #endif --> JSC…

网盘——登录跳转

在界面设计这块&#xff0c;当登录界面上输入的账号和密码都正确的情况下&#xff0c;直接跳转到好友界面&#xff0c;否则不跳转 1、在opewidget.h里面定义一个单例模式 static OpeWidget &getInstance(); 2、添加定义 产生一个静态的操作界面的对象。操作界面这个对象他…

MapTracker:Tracking with Strided Memory Fusion for Consistent Vector HD Mapping

参考代码&#xff1a;MapTracker 动机与出发点 为了提升帧间检测的稳定性通常会添加时许信息&#xff0c;这个可以BEV特征处做时序融合&#xff0c;也可以是用当前帧query去cross-attn历史帧信息&#xff0c;则更多的时候是将之前帧信息与当前做融合或者cross-attn实现信息传…

ReLU Strikes Back: Exploiting Activation Sparsity in Large Language Models

iclr 2024 oral reviewer 评分 688 1 intro 目前LLM社区中通常使用GELU和SiLU来作为替代激活函数&#xff0c;它们在某些情况下可以提高LLM的预测准确率 但从节省模型计算量的角度考虑&#xff0c;论文认为经典的ReLU函数对模型收敛和性能的影响可以忽略不计&#xff0c;同时…

亚信安慧AntDB-T数据库重分布的实现原理

摘要&#xff1a; 亚信安慧AntDB-T是一款通用企业级、高可用、高性能的原生分布式关系型数据库&#xff0c;具有多种分片方式。在数据库的使用过程中&#xff0c;随着数据的变更和增长&#xff0c;需要重新修改表的分片方式。 AntDB-T数据库支持重分布命令&#xff0c;在内核…

如何在极狐GitLab 启用依赖代理功能

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何在[极狐GitLab…

【测试开发学习历程】python面向对象

1 面向对象的基本概念 面向对象&#xff1a;是把构成问题事务分解成各个对象&#xff0c;建立对象的目的不是为了完成一个步骤&#xff0c;而是为了描叙某个事物在整个解决问题的步骤中的行为。 怎么理解面向对象&#xff1f; 面向对象是一种编程思想&#xff0c;就是把要解决…

Substance 3D2024版 下载地址及安装教程

Substance 3D是Adobe公司推出的一套全面的3D设计和创作工具集合&#xff0c;用于创建高质量的3D资产、纹理和材质。 Substance 3D包括多个功能强大的软件和服务&#xff0c;如Substance 3D Painter、Substance 3D Designer和Substance 3D Sampler等。这些工具提供了广泛的功能…

了解大语言模型的参数高效微调(Parameter-Effcient Fine-Tuning)

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 大语言模型在众多应用领域实现了突破性的进步&#xff0c;显著提升了各种任务的完成度。然而&#xff0c;其庞大的规模也带来了高昂的计算成本。这些模型往往包含数十亿甚至上千亿参数&#xff0c;需要…

VRRP虚拟路由实验(华为)

思科设备参考&#xff1a;VRRP虚拟路由实验&#xff08;思科&#xff09; 一&#xff0c;技术简介 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;是一种网络协议&#xff0c;用于实现路由器冗余&#xff0c;提高网络可靠性和容错能力。VRRP允许多台路由器…

vue商城项目vue shop vite

Vue Shop 是一个基于 Vue.js 框架构建的电子商务平台&#xff0c;它利用了 Vue 的响应式数据绑定和组件化的特点&#xff0c;为用户提供了一种快速开发和部署在线商店的解决方案。Vite 是一种现代化的前端构建工具&#xff0c;它提供了快速的冷启动、即时模块热更新&#xff08…

Elasticsearch:从 ES|QL 到 PHP 对象

作者&#xff1a;来自 Elastic Enrico Zimuel 从 elasticsearch-php v8.13.0 开始&#xff0c;你可以执行 ES|QL 查询并将结果映射到 stdClass 或自定义类的 PHP 对象。 ES|QL ES|QL 是 Elasticsearch 8.11.0 中引入的一种新的 Elasticsearch 查询语言。 目前&#xff0c;它在…

Understanding Diffusion Models: A Unified Perspective翻译和公式补充解读

“Understanding Diffusion Models: A Unified Perspective”是一篇写的非常好的扩散模型DDPM数学原理解读文章&#xff0c;这里翻译了一遍&#xff0c;对于一些细节补充记录一下&#xff0c;方便对照原文更好的理解。 这篇文章作者是Calvin Luo&#xff0c;来自Google Resear…

软考120-上午题-【软件工程】-软件开发模型02

一、演化模型 软件类似于其他复杂的系统&#xff0c;会随着时间的推移而演化。在开发过程中&#xff0c;常常会面临以下情形&#xff1a;商业和产品需求经常发生变化&#xff0c;直接导致最终产品难以实现&#xff1b;严格的交付时间使得开发团队不可能圆满地完成软件产品&…

AI论文速读 | TF-LLM:基于大语言模型可解释性的交通预测

论文标题&#xff1a; Explainable Traffic Flow Prediction with Large Language Models 作者&#xff1a;Xusen Guo, Qiming Zhang, Mingxing Peng, Meixin Zhu(朱美新)*, Hao (Frank)Yang(杨昊) 机构&#xff1a;香港科技大学&#xff08;广州&#xff09;&#xff0c;约翰…

C# 操作PDF表单 - 创建、填写、删除PDF表单域

通常情况下&#xff0c;PDF文件是不可编辑的&#xff0c;但PDF表单提供了一些可编辑区域&#xff0c;允许用户填写和提交信息。PDF表单通常用于收集信息、反馈或进行在线申请&#xff0c;是许多行业中数据收集和交换的重要工具。 PDF表单可以包含各种类型的输入控件&#xff0…

【软件工程】UML用例图介绍和实例说明

文章目录 1、什么是用例图2、用例图的作用3、怎么画用例图4、三要素说明5、实例说明 1、什么是用例图 用例图&#xff08;Use Case Diagram&#xff09;是统一建模语言&#xff08;UML&#xff09;的一种图&#xff0c;它主要用于描述系统的功能和用户&#xff08;参与者&…