蓝桥杯嵌入式模板(cubemxkeil5)

LED

引脚PC8~PC15,默认高电平(灭)。

此外还要配置PD2为输出引脚(控制LED锁存) ,默认低电平(锁住)!!!

#include "led.h"

void led_disp(unsigned char disp_led)
{
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_ALL,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOC,disp_led<<8,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

/*使用方法*/
unsigned char ledon=0x00;
led_disp(ledon|=0x01);//第一个led亮
led_disp(ledon|=0x04);//第三个led亮

led_disp(ledon&=~(0x01))//第一个led灭
led_disp(ledon&=~(0x08))//第四个led灭

KEY

选择PB0~PB2,PA0为输入模式,配置成上拉输入。 我们按键用的是定时器轮询检测按键状态(还能实现长按短按的功能)。

时钟源选择内部时钟,设置成100Hz,也就是10ms进一次中断,别忘了在NVIC Settings打勾 

#include "intterrupt.h"

struct keys
{
    unsigned char sta;//引脚电平
    unsigned char flag;//是否按下
    unsigned char longflag;//是否长按
    unsigned char judge;//进度标志位
    unsigned int time;//长按时要用到
};
struct keys key[4]={0,0,0};

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIMX)
    {
        key[0].sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
        key[1].sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
        key[2].sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
        key[3].sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);

        for(int i=0;i<4;i++)
        {
            switch(key[i].judge)
            {
                case 0:
                {
                    if(key[i].sta==0)
                    {
                        key[i].judge=1;
                        key[i].time=0;
                    }
                }
                break;
                case 1:
                {
                    if(key[i].sta==0)
                    {
                        key[i].judge=2;
                    }
                    else
                    {
                        key[i].judge=0;
                    }
                }
                break;
                case 2:
                {
                    if(key[i].sta==1)//松手的时候根据time来判断长短按
                    {
                        key[i].judge=0;
                        if(key[i].time<200)//小于2s
                        {
                            key[i].flag=1;
                        }
                    }
                    else//没松手
                    {
                        key[i].time++;
                        if(key[i].time>200)//大于2s
                        {
                            key[i].longflag=1;
                        }
                    }
                }
                break;
            }
        }
    }
}

/*使用方法*/

void key_proc(void)
{
    if(key[0].flag==1)//按键1短按
    {
        //处理数据
        key[0].flag=0;
    }
    if(key[3].longflag==1)//按键4长按
    {
        //处理数据
        key[3].longflag=0;
    }
}

key_proc()丢while里。


ADC

板子从左往右数第一个是PB15引脚(对应ADC2的通道15),第二个是PB12引脚(对应ADC1的通道11),采样周期选到最大,一定程度上能防止adc一直抖动。

#include "myadc.h"

double adc_get(ADC_HandleTypeDef *pin)
{
    unsigned int adc;
    HAL_ADC_Start(pin);
    adc=HAL_ADC_GetValue(pin);
    //HAL_Delay(1);可不加
    return adc*3.3/4096;                                                                                                                                                                           
}

/*使用方法*/
adc_get(&hadc2);//获取第一个电压
adc_get(&hadc1);//获取第二个电压

PWM

假设题目要求我们在PA7引脚输出频率为1000Hz,占空比为50%的PWM波

注意所选定时器最好不要和按键中断的定时器共用 !

frq=80000000/800/100;duty=50/100;

//在while之前启动PWM
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);

/*设置占空比和频率*/
__HAL_TIM_SET_PRESCALER(&htim17,80000000/100/PWM_frq);//设置频率


__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,duty);//设置占空比

IC

PB4和PA15引脚用于输入捕获,测量频率。最好用TIM2和TIM3! 按键定时器等所有外设都设置好了再设置。

#include "intterrupt.h"

unsigned int ccrl_val=0;
unsigned int frq=0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM2)
    {
        ccrl_val=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
        __HAL_TIM_SetCounter(htim,0);
        frq=(80000000/80)/ccrl_val;
        HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
    }
    //if(htim->Instance==TIM3)
    //{
    //  
    //}
    //同上 再定义一个变量即可 注意在main里extern frq
}

/*使用方法*/
//在while之前启动IC 就可以在while里读frq
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//启动第一个IC
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);//启动第二个IC

IC(测量占空比) 

假设题目要求我们检测PA7引脚输入的信号的占空比

cubemx如上配置,PA7对应TIM3的通道二,那么把通道二设置成直接模式,另外选一个通道设置成间接模式,让直接模式测量上升沿,间接模式测量下降沿。

#include "intterrupt.h"

unsigned int ccrl_vala=0,ccrl_valb=0;
unsigned int frq=0;
double duty=0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM3)
    {
        ccrl_vala=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);//直接
        ccrl_valb=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);//间接
        __HAL_TIM_SetCounter(htim,0);
        frq=(80000000/80)/ccrl_vala;
        duty=(double)(ccrl_valb/ccrl_vala)*100;
        HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
        HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_2);
    }
}

 这个看看就好 考的几率不大。


UART

记得手动选择PA9和PA10,波特率按题目要求,一般是9600。记得开中断!!! 

#include "interrupt.h"
#include "usart.h"

char rxdata[22];
unsigned char rxbit;
unsigned char rx_p;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    rxdata[rx_p++]=rxbit;
    HAL_UART_Receive_IT(&huart1,&rxbit,1);
}

/*使用方法*/
include "string.h"//使用memset函数
//在while之前初始化 调用HAL_UART_Receive_IT(&huart1,&rxbit,1);

void uart_proc(void)
{
    if(rx_p>0)
    {
        if(rx_p==x)//实际要接收的位数
        {
            //处理
        }
        else
        {
            //报错
        }
        rx_p=0;
        memset(rxdata,0,22);//22要和你设置的rxdata长度一样
    }
}

/*注意事项*/
//在while循环里这样写 防止接收不完整
while(1)
{
    if(rx_p!=0)
    {
        uint8_t temp=rx_p;
        HAL_Delay(1);
        if(rx_p==temp)
        {
            uart_proc();
        }
    }
}

I2C

直接在官方给的i2c_hal.c里写,cubemxPB6和PB7直接选择输出模式。

#include "i2c_hal.h"//官方的.c函数

void eeprom_write(unsigned char addr,unsigned char dat)
{
    I2CStart();

    I2CSendByte(0xa0);//0表示写
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    I2CSendByte(dat);
	I2CWaitAck();

    I2CStop();
}

unsigned char eeprom_read(unsigned char addr)
{
    unsigned char dat;
    I2CStart();
    
    I2CSendByte(0xa0);//0表示写
    I2CWaitAck();
    I2CSendByte(addr);
    I2CWaitAck();
    I2CStop();

    I2CStart();
	I2CSendByte(0xa1);//1是读
	I2CWaitAck();
    dat=I2CReceiveByte();
	I2CSendNotAck();//读出来之后发送非应答
    I2CStop();
	return dat;
}

/*使用方法*/
eeprom_write(0,data);//地址从0开始,存八位的数据。

data=eeprom(0);//读地址

八位无符号整型数据可以直接写和读,double类型的参考下图;

注意:每次写入都要延时5ms!!!  


RTC

 

近几年基本不考,但要会最基本的rtc时钟。参数填125和6000。

#include "stdio.h"

RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;

while(1)
{
    HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);//一定要先获取时间再获取日期!!!
    HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);
    
    char text[50];
    sprintf(text,"%02d:%02d:%02d--%02d:%02d:%02d",sDate.Year,sDate.Month,sDate.Date,sTime.Hours,sTime.Minutes,sTime.Seconds);
    //再用官方提供的lcd显示函数显示年月日时分秒即可
}

RTC暂停:__HAL_RCC_RTC_DISABLE(); 

RTC恢复:__HAL_RCC_RTC_ENABLE(); 


 RTC闹钟

记得开中断,闹钟先设置成3s后

RTC_AlarmTypeDef sAlarm;

void GET_Time(void)
{
	HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
}
 
void SET_alarm(void)
{
  sAlarm.AlarmTime.Hours = 0x00;
  sAlarm.AlarmTime.Minutes = 0x0;
/**/sAlarm.AlarmTime.Seconds = sTime.Seconds+1;
  sAlarm.AlarmTime.SubSeconds = 0x0;
  sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS
                              |RTC_ALARMMASK_MINUTES;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 0x1;
  sAlarm.Alarm = RTC_ALARM_A;
/**/if(sAlarm.AlarmTime.Seconds==60)sAlarm.AlarmTime.Seconds=0;
/**/HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);//这里要注意,我们选择的是十进制
}

//中断服务函数
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
	GET_Time();
	SET_Alarm();
    //操作
}

 SET_alarm里加了多行注释的是自己添加的东西,其余从rtc.c复制

每一秒进一次rtc闹钟的回调函数,在回调函数里进行对应的操作即可。

(可能不考,了解即可) 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Boot 源码学习】SpringApplication 的 run 方法核心流程介绍

《Spring Boot 源码学习系列》 SpringApplication 的 run 方法核心流程介绍 一、引言二、往期内容三、主要内容3.1 run 方法源码初识3.2 引导上下文 BootstrapContext3.3 系统属性【java.awt.headless】3.4 早期启动阶段3.5 准备和配置应用环境3.6 打印 Banner 信息3.7 新建应用…

ETL快速同步用友u8数据方式

在企业信息化进程中&#xff0c;用友U8作为一款广泛应用的ERP系统&#xff0c;承载着企业核心业务数据。为了实现这些数据的有效利用与深度分析&#xff0c;往往需要通过ETL&#xff08;Extract, Transform, Load&#xff09;工具进行快速、准确的数据同步。本文将详细阐述ETL快…

Spring中的适配器模式

在Spring MVC框架中&#xff0c;适配器模式主要体现在对不同类型的处理器&#xff08;即Controller&#xff09;的统一处理上。Spring MVC通过适配器模式来保证无论Controller的实现方式如何多样化&#xff0c;都能够被DispatcherServlet统一调用和管理。具体使用方式如下&…

基于LabVIEW的CAN通信系统开发案例

基于LabVIEW的CAN通信系统开发案例 介绍了基于LabVIEW开发的CAN通信系统&#xff0c;该系统主要用于汽车行业的数据监控与分析。通过对CAN通信协议的有效应用&#xff0c;实现了车辆控制系统的高效信息交换与实时数据处理&#xff0c;从而提升了车辆性能的检测与优化能力。 项…

使用冒泡排序模拟实现qsort函数

目录 冒泡排序qsort函数的使用1.使用qsort函数排序整型数据2.使用qsort函数排序结构数据 冒泡排序模拟实现qsort函数今日题目1. 字符串旋转结果2.杨氏矩阵3.猜凶手4.杨辉三角 总结 冒泡排序 冒泡排序的核心思想是:两两相邻的元素进行比较 代码如下: //⽅法1 void bubble_so…

柯桥地区职业学校日语口语常用成人零基础入门

在日语中,“做饭”有几种表达方式: 1. 料理する 是最常用的说法,意思就是“做料理”。 例句: 毎日妻が料理をしている。 每天妻子都在做饭。 2. 食事を作る 意思是“做饭”,“制作膳食”。 例句: 友達のために食事#15857575376を作った。 为朋友做了饭。 编辑搜图 请点…

在uni-app使用iconfont中的图标

uni-app 如何使用iconfont中的图标 在uni-app中使用Iconfont图标通常涉及以下几个步骤&#xff1a; 步骤一&#xff1a;获取Iconfont资源 访问 iconfont-阿里巴巴矢量图标库&#xff0c;注册并登录账号。 浏览或搜索所需的图标&#xff0c;将它们添加至购物车或直接创建项目进…

下一代换脸和数字人生成神器Facefusion又更新了(懒人包)

号称“下一代换脸和数字人生成神器”的Facefusion软件在2024年3月底发布了最新的2.4.1版本&#xff0c;带来了一系列的更新和改进&#xff0c;使得人脸融合和分析技术更加易用和高效&#xff0c;以及一些性能和功能方面的全面提升。 Facefusion2.4.1版本更新亮点 Facefusion新…

【面试题】s += 1 和 s = s + 1的区别

文章目录 1.问题2.发现过程3.解析 1.问题 以下两个程序真的完全等同吗&#xff1f; short s 0; s 1; short s 0; s s 1; 2.发现过程 初看s 1 和 s s 1好像是等价的&#xff0c;没有什么区别。很长一段时间内我也是这么觉得&#xff0c;因为当时学习c语言的时候教科书…

Python学习笔记23 - 目录操作

os模块操作目录相关函数 os.path模块操作目录相关函数 案例1 —— 列出指定目录下的所有.py文件 案例2 —— walk()

模电和数电哪个更难学?

模电和数电各有其难点&#xff0c;因此很难说哪个更难。 模拟电路&#xff08;模电&#xff09;涉及到连续的电压和电流信号&#xff0c;其分析和设计需要考虑许多因素&#xff0c;如信号失真、噪声、频率响应等。模电的设计通常需要考虑更多的物理参数和元件特性&#xff0c;…

李廉洋:4.15黄金,原油最新资讯,美盘走势分析及策略。

由于欧洲央行很可能先于美联储降息&#xff0c;美元走强。法国兴业银行分析师基特•朱克斯表示&#xff0c;市场“假设我们看到欧洲央行将在6月降息&#xff0c;但美联储不会”&#xff0c;这对美元有利。朱克斯表示&#xff0c;尽管在货币政策决定之前会公布一些相关数据&…

Web应用程序中的常见安全漏洞

大家好&#xff0c;我是咕噜铁蛋&#xff01;今天&#xff0c;我想和大家聊聊一个在我们日常开发中经常遇到的问题——Web应用程序中的安全漏洞。在这个数字化时代&#xff0c;Web应用几乎无处不在&#xff0c;它们不仅方便了我们的生活&#xff0c;也推动了社会的进步。然而&a…

中霖教育:一建需不需要继续教育?

根据规定&#xff0c;一级建造师必须在其注册期内完成规定的继续教育学时&#xff0c;否则无法进行注册延期。 一级建造师的注册证书的有效期限设定为三年&#xff0c;为确保资格的有效性并申请续期&#xff0c;持证者需在该有效期内满足制定的继续教育标准。 继续教育课程结…

windows应急中的快捷键

windows应急中的快捷键 应急的时候&#xff0c;快捷键很重要&#xff0c;记录一下windows主机排查需要用到的快捷键 windows快捷键 appwiz.cpl 是打开安装面板 程序和功能 控制面板程序和功能 搜索程序和功能 控制而板主页 卸载或更改程序 若要卸酸程序,请从列表中将其…

【Java探索之旅】数组概念与初始化指南:动静结合

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、初识数组1.1 为什么要有数组&#xff1f;1.2 数组的的概念 二、数组的创建及初始化…

多模态(clip/ALBEF)

一. CLIP 1. clip的核心思想是通过海量的弱监督文本对通过对比学习&#xff0c;将图片和文本通过各自的预训练模型获得的编码向量在向量空间上对齐。 clip 的text encode: 在Text Encoder中&#xff0c;我们会对每个句子增加一个Class Token&#xff0c;用于整合特征&#x…

排序算法—堆排序

文章目录 堆排序堆思路过程建堆排序 代码实现 堆排序 时间复杂度&#xff1a;O(N*logN) 稳定性&#xff1a;不稳定&#xff08;相同元素排序后的相对位置改变&#xff09; 堆 堆的逻辑结构是一棵完全二叉树&#xff1b;堆的物理结构是一个数组&#xff0c;通过下标表示父子结…

推荐5款 深受欢迎 的AI开源项目

本周 GitHub圈选 项目推荐&#xff1a; InstantID&#xff08;小红书AI图像生成工具&#xff09; CWMP&#xff08;ChatGPT Web Midjourney Proxy&#xff09; aicover&#xff08;AI红包封面制作神器&#xff09; ML-YouTube-Courses&#xff08;机器学习的学习库&#xff…