蓝桥杯嵌入式省赛总结

【2023蓝桥杯 嵌入式组适用】CT117E-M4 新款开发板 3小时省赛模块 速成总结 纯分享,零套路,永久免费_哔哩哔哩_bilibili

上视频,有一定STM32基础的同学可以通过该视频快速了解,蓝桥杯嵌入式省赛各个模块的使用方法,小白不建议直接看。

下面是一些资料分享:

1、8~13界省赛代码

【蓝桥杯嵌入式】第十三届至第八届真题演示(附代码)_哔哩哔哩_bilibili

2、各界客观题资料

(有的客观题,学会查看官方给的手册其实更快一些,不过不用执着与客观题,看看就行,程序题才是大头)

#蓝桥杯嵌入式组#历年客观题解析_蓝桥杯嵌入式客观题_vircorns的博客-CSDN博客

嵌入式蓝桥杯客观题总结(4.19)_蓝桥杯嵌入式客观题_little.jet的博客-CSDN博客

【蓝桥杯嵌入式组】一、客观题(赛前必看) - 知乎 (zhihu.com)

3、省赛资源包

链接:https://pan.baidu.com/s/1T6nhFgYjTYOYtzJhofkgrw?pwd=nf0g 
提取码:nf0g

4、各个模块的代码

(可以在观看完开头分享的学习视频后,当作代码速查速记资料)

----------------------------------------------------------------------------------------------------------------------

1、常用函数复习

stdio.h  :

char text[30];

sprintf(text,"       PSD          ");

sscanf(text,"%3s-%3s",code1,code2);

string.h  :

strlen()

strcmp( , )  两字符串相同返回0

memset( , , )  内存赋值,memset(数组名,清零,数组长度)

stdlib.h  :

atoi()  将字符串转换成整数型

stdbool.h :

bool

----------------------------------------------------------------------------------------------------------------------

2、.h文件框架

#ifndef _INTERRUPUT_H_

#define _INTERRUPUT_H_

#endif

----------------------------------------------------------------------------------------------------------------------

3、初始化设置(在main.c中)

led_disp(0x00); // 初始化,灯全灭

LCD_Init();

LCD_Clear(Black);

LCD_SetBackColor(Black);

LCD_SetTextColor(White);

HAL_TIM_Base_Start_IT(&htim4);  // 使能定时器,IT是指中断开启

HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1); // pwm输出开启

HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);

HAL_UART_Receive_IT(&huart1,&rxdat1,1);  // 串口开启

// 测量频率只需要打开一个通道。捕获上升沿,测一个周期的计数值。

// 测量占空比需要打开两个通道。直接通道捕获上升沿,测一个周期的计数值;间接通道捕获下降沿,测高电平的计数值。(CubMX上配置)

HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//频率测量捕获定时器开启 直接通道

HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);//频率测量捕获定时器开启 间接通道

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);

// 初始化频率,占空比

__HAL_TIM_SET_AUTORELOAD(&htim16, freq1);

__HAL_TIM_SET_AUTORELOAD(&htim17, freq2);

__HAL_TIM_SET_COMPARE(&htim16,TIM_CHANNEL_1,pwm1);

__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,pwm2);

// __HAL_TIM_SET_AUTORELOAD() 是修改分频系数的,STM32CubeMX中的Counter Period不变,改变分频系数来改变频率。(例如 80MHZ,分频:800-1,Counter Period:100-1,现在是100HZ。要改成1000HZ,则freq1=80-1)

// __HAL_TIM_PRESCALER()好像也能用来修改频率,用法与上同

// 将定时器16通道1的比较值设为100 (pwm1),如果Counter Period为1000 (cubeMX中设置的),则占空比为10%

// While 1 中串口接收程序

While(1)

{

        if(rx_pointer!=0)

        {

                int temp=rxdat1;

                HAL_Delay(1);

                if (temp==rxdat1)

                uart_rx_proc();//完成接收

        }

}

/*按键函数中只写标志位的改变,再转到while(1)中通过判断标志位来写灯、pwm频率占空比等的改变,因为按键函数中只有当按下才进去一次,后续功能可能执行不完整----可参考第十三届试题*/

// 串口发送

char temp[20];

sprintf(temp,"frq=%d\r\n",frq1);

HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);

// 串口接收-----第十二届试题

extern char rxdata[30];

extern uint8_t rxdat;

extern uchar rx_pointer;

char car_type[5];

char car_data[5];

char car_time[13];

void usart_rx(void)

{

        if(rx_pointer>0)

        {

                if(rx_pointer==22)

                {

                        sscanf(rxdata,"%4s:%4s:%12s",car_type,car_data,car_time);

                }

                else

                {

                        char temp[20];

                        sprintf(temp,"Error\r\n");

                        HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);

                }

                rx_pointer=0;        // 指针归位

                memset(rxdata,0,30);  // 清除数据,memset(数组名,清零,数组长度)

        }

}

----------------------------------------------------------------------------------------------------------------------

4、LED配置

#include "led.h"  --- 可写到interrupt中

void led_disp(uchar displed)

{

        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET);  // 熄灭所有灯

        HAL_GPIO_WritePin(GPIOC, displed<<8, GPIO_PIN_RESET);  // 点灯,左移8位

        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);

        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

}

/*

led_disp(0x01);   // LED1亮

led_disp(0x02);   // LED2亮

led_disp(0x04);   // LED3亮,

// led_disp(0x03)二进制是011,是LED1和LED2亮,不是LED3亮

*/

----------------------------------------------------------------------------------------------------------------------

5、ADC采集

#include "myadc.h"  --- 可写到interrupt中

double adc_read(ADC_HandleTypeDef *pin)

{

        uint adc;

        HAL_ADC_Start(pin);

        adc = HAL_ADC_GetValue(pin);

        return adc*3.3/4096;   // ADC12位,2^12=4096

}

// 使用方法:   adc_read(&hadc2)   

--------------------------------------------------------------------------------------------------------------------

6、各种中断回调函数--按键、测PWM频率/占空比、串口通信等

#include "interrupt.h"

#include "usart.h"  // 用串口时要包涵头文件!!!!!

#include "stdbool.h"   // 使用 bool,要包含头文件

struct keys
{
    uchar judge_flag;
    bool key_state;   
    bool key_short;  // 短按标志
    bool key_long;   // 长按标志
    uint key_time;    // 按键按下计时
};

struct keys key[4] = {0,0,0,0}; 

uint16_t led_5cnt=0;

uint16_t led_bling=0;

uchar led_5=0;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) // cubemx中设置10ms/次

{

        if(htim->Instance == TIM4)  // 要在这个判断里面!!

        {

                if(++led_bling == 20)  //  0.1秒闪烁,0.2秒一个周期

                led_bling = 0;

                if(++led_5cnt == 500)  // 定时5秒

                {

                        led_5 = 1;

                        led_5cnt = 0;     

                }

                key[0].key_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);

                key[1].key_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);

                key[2].key_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);

                key[3].key_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

                for(int i=0; i<4; i++)

                {

                        switch (key[i].jugde_flag)

                        {

                                case 0:

                                {

                                        if(key[i].key_state == 0)

                                        {

                                                key[i].jugde_flag = 1;

                                                key[i].key_time = 0;

                                        }

                                }break;

                                case 1:

                                {

                                        if(key[i].key_state == 0)           // 消抖

                                                key[i].jugde_flag = 2;

                                        else

                                                key[i].jugde_flag = 0;

                                }break;

                                case 2:

                                {

                                          if(key[i].key_state == 1)         // 按键松开

                                          {

                                                if(key[i].key_time<70)

                                                {

                                                        key[i].key_short=1;

                                                }

                                                key[i].judge_flag=0;

                                          }

                                          else

                                          {

                                                key[i].key_time++;

                                                if(key[i].key_time>=70)

                                                {

                                                        key[i].key_long=1;

                                                }

                                          }

                                    }break;

                            }

                  }

        }

}

/*----------------------------------------------------------------------------------------------------------------

函数中判断满足条件后(incorrect_ref==1),要先将led_5cnt,led_bling,led_5都清零,然后开始定时中断

例如while(1)中:

if(incorrect_ref==1)   //  LED2以0.1秒闪烁,闪烁5秒熄灭,incorrect_ref中断开启标志位

{

        if(led_bling <=10)   

        {

                LED_disp(0x02);

        }

        else if(led_bling >10)

        {

                LED_disp(0x00);

        }

        if(led_5==1)

        {

                incorrect_ref=0;   

                LED_disp(0x00);

                led_5=0;

        }

}

---------------------------实现时钟,该代码在中断回调函数中,参考第8界省赛题-------------------------

uint8_t time_hours=12;

uint8_t time_minute=59;

uint8_t time_seconds=50;

uint8_t time_tt=0;

if(++time_tt==100)   // 定时器10ms一次,100次就是1s

{

        time_tt=0;

        if(++time_seconds==60)

        {

                time_seconds=0;

                if(++time_minute==60)

                {

                        time_minute=0;

                        if(++time_hours==13)  // 12小时进制计数

                        {

                                time_hours=0;

                        }

                }

        }

}

------------------------------------------------------------------------------------------------------------*/

// -----测频率---占空比-----

uint time1_vaul = 0, time2_vaul = 0;

uint freq = 0;

float pulse = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) // 回调函数

{

        if(htim->Instance == TIM2)

        {

                time1_vaul = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);  

                // 捕获计数器的值,一个周期

                time2_vaul = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);  

                // 捕获计数器的值,高电平

                __HAL_TIM_SetCounter(htim, 0);           // 计数值清零

                freq = (80000000/80)/time1_vaul;          // 时钟80MHZ,设置的80分频

                pulse = time2_vaul/time1_vaul*100;        // 占空比

                HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_1);  // 重新开启定时器

                HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_2);

        }

}

// 串口接收

char rxdata[30];

uint8_t rxdat1;

uchar rx_pointer;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

      HAL_UART_Receive_IT(&huart1,&rxdat1,1);     // 要包含头文件#include "usart.h",不然报错

      rxdata[rx_pointer++]=rxdat1;

}

-------------------------------------------------------------------------------------------------------------------

7、eeprom使用,在官方给的I2C文件中添加读写函数即可

#include "i2c - hal.h"

uchar eeprom_read(uchar addr)

{

        uchar dat;

        I2CStart();

        I2CSendByte(0xa0);   // 0xa0写,0xa1读;查看AT24C02芯片手册

        I2CWaitAck();

        I2CSendByte(addr);

        I2CWaitAck();

        I2CStop();

        I2CStart();

        I2CSendByte(0xa1);

        I2CWaitAck();

        dat=I2CReceiveByte();

        I2CWaitAck();

        I2CStop();

        return dat;

}

void eeprom_write (uchar addr,uchar dat)

{

        I2CStart();

        I2CSendByte(0xa0);

        I2CWaitAck();

        I2CSendByte(addr);

        I2CWaitAck();

        2CSendByte(dat);

        I2CWaitAck();

        I2CStop();

}

--------------------------------------------------------------------

// 存储值到eeprom中,注意eeprom读写是8位的!!!

// 例:16位数据类型要拆分高8位,低8位。

uchar adc1, adc_h, adc_l;

adc1 = readADC(&hadc1);

adc_h = adc1 >> 8;     // 高8位

adc_l = adc1 & 0xff;    // 低8位

eeprom_write(1,adc_h);

eeprom_write(2,adc_l);

// 读取时也要注意是8位读取

adc1 = (eeprom_read(1)<<8) + eeprom_read(2);   // 注意<<优先级低于+,要带括号!

---------------------------------------------------------------------

// 还有32位整形,浮点数的eeprom存取--始终记得eeprom是8位的!!!好像就考过难一点的就是浮点数的存储,可以先将浮点数扩大10或者100倍当作整形或者char型来处理。这么麻烦不要也罢,嗯,美名其曰懂得取舍!

// 32位整形数据读写

void wirte_32b(uint8_t add,uint32_t data)

{

        eeprom_write(add,data&0xff);

        HAL_Delay(2);

        eeprom_write(add+1,(data>>8)&0xff);

        HAL_Delay(2);

        eeprom_write(add+2,(data>>16)&0xff);

        HAL_Delay(2);

        eeprom_write(add+3,(data>>24)&0xff);

        HAL_Delay(2);

}

uint32_t read_32b(uint8_t add)

{

        uint32_t temp;

        temp=eeprom_read(add);

        HAL_Delay(2);

        temp+=eeprom_read(add+1)<<8;

        HAL_Delay(2);

        temp+=eeprom_read(add+2)<<16;

        HAL_Delay(2);

        temp+=eeprom_read(add+3)<<24;

        HAL_Delay(2);

        return temp;

}

// 浮点型数据读写

void write_flo(uint8_t add,float data)

{

        uint32_t temp;

        temp = (uint32_t)(data*100);

        wirte_32b(add,temp);

}

float read_flo(uint8_t add)

{

        uint32_t temp;

        temp=read_32b(add);

        return (float)temp/100;

}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值