蓝桥杯嵌入式学习攻略笔记

用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历

  • 工具
  • 环境准备
  • cubemx配置
  • 外部高速时钟使能
  • 设置串口
  • 时钟配置
  • 项目配置
  • keil配置
  • 烧录方式
  • 注意
  • 代码规范
  • 头文件配置
  • 模块
  • led
  • cubemx配置
  • keil代码
  • 实现点亮一只灯
  • 实现具体操作的灯,以及点亮还是熄灭
  • 按键
  • cubemx配置
  • keil代码
  • LCD
  • keil代码
  • 引脚冲突问题
  • LED闪烁
  • cubemx配置
  • keil代码
  • 按键长按
  • cubemx配置
  • keil代码
  • LCD高亮显示
  • keil代码
  • PWM输出
  • 计算公式
  • cubemx配置
  • keil代码
  • 输入捕获测量引脚输出PWM波周期
  • 原理图
  • 要求:用PA7来测量PA1生成PWM波的频率
  • cubemx配置
  • keil代码
  • 输入捕获测量555定时器频率
  • 原理图
  • cubemx配置
  • keil代码
  • ADC测量
  • 原理图
  • cubemx配置
  • keil代码
  • 串口发送和接收
  • 原理图
  • cubemx配置
  • keil代码
  • 利用定时器进行串口不定长数据接收
  • 原理
  • cubemx配置
  • keil代码
  • EEPROM读写
  • 原理
  • keil代码
  • 工具

    keil5,stm32cube

    环境准备

    根据赛事方提供的板子来选择cubemx上的器件
    。。。

    cubemx配置

    外部高速时钟使能

    外部高速时钟使能

    设置串口

    时钟配置

    时钟配置为24MHZ因为外部晶振为24MHZ,其余的暂时不清楚原因

    项目配置

    配置为MDK
    需要注意,固件地址需要设置为下载解压后的文件地址(提前从数据包中下载)

    勾选生成.c.h文件

    注意一下,下载好软件后,要解压固件包,然后在help中设置地址

    keil配置

    烧录方式


    烧录设置

    要是没有芯片包,需要从赛事数据包中解压,会自动生成

    keil代码自动补全
    点击edit,configraution选择跟编译相关的Text Completion,然后勾线第三个

    注意

    代码需要写入begin – end之间

    代码规范

    新建code文件夹
    右键CMSIS,点击Manage Project,新建一个文件夹

    点击魔术棒,c++,include path,添加文件夹路径

    然后添加fun.c,fun.h,headfile.h 三个文件
    头文件可能显示不出来,所以需要添加existing file 再勾选all file,即可添加

    头文件配置

    headfile.h

    fun.h

    fun.c

    main.c

    模块

    led

    led引脚分配图
    通过观察开发板led电路图可以发现,led的的引脚控制由PC8~15低电平点亮,同时PD2锁存器控制开关,需要置高电平

    cubemx配置

    将PC8~15设置为输出,PD2设置为输出
    在GPIO配置中,将引脚全部配置为高电平,使得上电时LED灭

    keil代码

    实现点亮一只灯

    fun.c主要代码

    void led_show()
    {
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
    	
    	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
    	
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    
    
    }
    

    fun.h代码

    void led_show(void);
    

    main.c代码(需要在主函数内)

    led_show();
    
    实现具体操作的灯,以及点亮还是熄灭

    fun.c代码

    void led_show(uint8_t led, uint8_t mode)
    {
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
    	if(mode)
    		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_RESET); //GPIO_PIN_8的二进制代码为0000 0001 0000 0000 GPIO_PIN_9的二进制代码为0000 0010 0000 0000,所以用左移移位符
    	else
    		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_SET);
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    
    
    }
    
    

    fun.h代码(需要加上那个头函数)

    #include "stm32g4xx.h"                  // Device header
    
    
    void led_show(uint8_t led, uint8_t mode);
    

    main.c代码(灯1, 4,8亮)

    		led_show(1, 1);
    		led_show(4, 1);
    		led_show(8, 1);
    

    按键

    原理图,如图,需要将PB0~2,PA0配置为上拉输入模式。按下为低电平,松开为高电平

    cubemx配置

    ,PA0

    keil代码

    fun.c代码

    void key_scan()
    {
    	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    	B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
    	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    	if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(1, 1);
    	}
    	if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(1, 0);
    	}
    	if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 1);
    	}
    	if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 0);
    	}
    	B1_last_state	= B1_state;
    	B2_last_state	= B2_state;
    	B3_last_state	= B3_state;
    	B4_last_state	= B4_state;
    
    
    }
    

    fun.h代码

    void key_scan(void);//里面没有这个void会有waring,但影响似乎不大
    

    main.c代码
    同样放入while循环中

    LCD

    首先在赛事方提供的数据包中找到液晶驱动参考程序,HAL库版本,找到lcd.c,font.h,lcd,h,复制到code文件夹,打开keil工程文件,添加这三个文件

    初始准备
    main.c函数

    headfile.h函数

    keil代码

    实现了在第一行显示字符,按键按下时,第三行数字变化的功能
    fun.c代码

    #include "headfile.h"
    
    int count = 0;
    
    void led_show(uint8_t led, uint8_t mode)
    {
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
    	if(mode)
    		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_RESET);
    	else
    		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_SET);
    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    
    
    }
    
    
    
    uint8_t B1_state;
    uint8_t B1_last_state;
    uint8_t B2_state;
    uint8_t B2_last_state;
    uint8_t B3_state;
    uint8_t B3_last_state;
    uint8_t B4_state;
    uint8_t B4_last_state;
    
    
    void key_scan()
    {
    	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    	B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
    	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    	if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		count ++;
    	}
    	if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		count --;
    	}
    	if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 1);
    	}
    	if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 0);
    	}
    	B1_last_state	= B1_state;
    	B2_last_state	= B2_state;
    	B3_last_state	= B3_state;
    	B4_last_state	= B4_state;
    
    
    }
    
    char text[20]; //linemax = 20
    
    void lcd_show()
    {
    	sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·û
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	sprintf(text, "     count: %d     ", count);
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    
    }
    
    

    fun.h代码

    #ifndef _fun_h
    #define _fun_h
    
    #include "stm32g4xx.h"                  // Device header
    
    
    void led_show(uint8_t led, uint8_t mode);
    
    void key_scan(void);
    
    void lcd_show(void);
    
    #endif
    
    
    

    main.c代码

    引脚冲突问题

    lcd和led的引脚有冲突

    解决办法:将PD2引脚提前置低电平,这样数据就不能传入led,led就不会点亮了,但是下次点亮led时依旧会出现这样的问题,所以需要将所有用到的LCD.C函数加上

    uint16_t temp = GPIOC->ODR;
    GPIOC->ODR = temp;
    

    解决方法如下
    main.c (在初始化部分)

    	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
    

    lcd.c (部分代码)


    问题成功解决!

    LED闪烁

    两个重要参数:PSC,ARR
    其中系统频率f为80MHZ,如果要让T=1,则可令ARR = 9999,PSC = 7999;即可确定定时周期为1

    初始化
    在headfile.h文件中添加tim.h文件头

    main.c

    cubemx配置

    需要配置定时器,正常使用通用定时器TIM2即可,重点是修改PSC和ARR


    生成代码后可发现多了tim.c函数,找到stm32g4xx_hal_tim.h文件里面的call_back回调函数

    将其复制到fun.c中

    keil代码

    在fun.c中定义一个变量

    uint8_t led_mode;
    

    按键长按

    原理,用一个计数器cnt(取10000)计时1s,20000对应2s,5000对应0.5s来计时,达到识别按键长按的目的

    cubemx配置

    此时TIM3不使能!!

    keil代码

    fun.c代码

    uint8_t B1_state;
    uint8_t B1_last_state;
    uint8_t B2_state;
    uint8_t B2_last_state;
    uint8_t B3_state;
    uint8_t B3_last_state;
    uint8_t B4_state;
    uint8_t B4_last_state;
    
    
    void key_scan()
    {
    	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    	B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
    	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    	if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		TIM3->CNT = 0;
    	}
    	else if(B1_state == 0 && B1_last_state == 0) //°´¼üB1Ò»Ö±°´ÏÂ
    	{
    		if(TIM3->CNT >= 10000)//°´¼üB1³¤°´
    		{
    				count++;
    		}
    	}
    	else if	(B1_state == 1 && B1_last_state == 0)//°´¼üB1ËÉ¿ª
    	{
    		if(TIM3->CNT < 10000)//°´¼üB1¶Ì°´
    		{
    			count += 2;
    		}
    	}
    	if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		count --;
    	}
    	if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 1);
    	}
    	if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ
    	{
    		led_show(2, 0);
    	}
    	B1_last_state	= B1_state;
    	B2_last_state	= B2_state;
    	B3_last_state	= B3_state;
    	B4_last_state	= B4_state;
    
    
    }
    

    main.c代码
    需要注意!给TIM3使能,但因为不是中断,是定时器,所以不用IT

    LCD高亮显示

    其实就是调用 LCD_SetBackColor(Color);这个函数,把背景颜色改成黄色

    keil代码

    定义变量

    uint8_t lcd_highshow;
    

    按键b1按下时

    			lcd_highshow ++;
    			lcd_highshow %= 3;	
    

    逻辑流程
    应该蛮简单的,就不写注释了

    void lcd_show()
    {
    	sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·û
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	if(lcd_highshow == 0)
    	{
    	LCD_SetBackColor(Yellow);
    	sprintf(text, "     count: %d     ", count);
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    	LCD_SetBackColor(Black);
    	sprintf(text, "     txysgdmn     ");
    	LCD_DisplayStringLine(Line4, (uint8_t *)text);
    	
    	sprintf(text, "     baozi     ");
    	LCD_DisplayStringLine(Line5, (uint8_t *)text); 
    	}
    	else if(lcd_highshow == 1)
    	{
    
    	sprintf(text, "     count: %d     ", count);
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    	LCD_SetBackColor(Yellow);
    	sprintf(text, "     txysgdmn     ");
    	LCD_DisplayStringLine(Line4, (uint8_t *)text);
    	LCD_SetBackColor(Black);
    	sprintf(text, "     baozi     ");
    	LCD_DisplayStringLine(Line5, (uint8_t *)text); 
    	
    	}
    
    

    PWM输出

    一般要求:让PA1输出频率为1000HZ,占空比为50%的方波

    计算公式

    cubemx配置

    keil代码

    在生成代码后,发现一个问题:文件中没有头文件!
    后面找到解决办法, 编译之后,就能知道每个文件依赖于哪些头文件!还是第一次遇到这种问题
    先在main.c函数中将定时器使能

    这个函数在头文件里找–stm32g4xx_hal_tim.h

    	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
    

    设置占空比

    	TIM2->CCR2 = 50;
    

    原理图(抄袭版),不懂的话看嵌入式的书去

    输入捕获测量引脚输出PWM波周期

    原理图

    要求:用PA7来测量PA1生成PWM波的频率

    需要用杜邦线连接PA7和PA1.

    cubemx配置

    这里PA7用TIM17或者TIM2都行,我就根据视频来了

    使能定时器

    keil代码

    为了省事,将code文件复制到这个工程目录下,记得在main.c文件中添加头文件定义

    main.c函数
    使能中断17

    	HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);
    

    fun.c代码
    参考着原理图一起理解

    #include "headfile.h"
    
    char	text[20]; 
    
    uint32_t fre, capture_value;
    
    void lcd_show()
    {
    	sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·û
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	sprintf(text, "   fre:%d   ", fre);
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    	}
    
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	if(htim->Instance == TIM17)
    	{
    		capture_value = TIM17->CCR1;
    		TIM17->CNT = 0;
    		fre = 80000000/(80*capture_value);
    	
    	}
    
    
    }
    
    

    main.c代码
    注意不要忘记了给LCD初始化

      /* USER CODE BEGIN 2 */
    	LCD_Init();
    	LCD_Clear(Black);
    	LCD_SetBackColor(Black);
    	LCD_SetTextColor(White);
    	
    	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
    	TIM2->CCR2 = 50;
    	
    	HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
    		lcd_show();
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    

    输入捕获测量555定时器频率

    实现效果:能测量出两个信号发生器输出的PWM波的频率,两个频率可以通过R39,和R40调节

    原理图

    cubemx配置

    将PA15设置为TIM2_CH1,PB4设置为TIM16_CH1;
    分别将两个定时器设置为输入捕获模式,PCC设置为80-1,并且使能

    keil代码

    main.c
    需要注意,不要忘记了LCD初始化,不要忘记了中断使能,不要忘记了把lcd_show函数放到循环里

      /* USER CODE BEGIN 2 */
    	LCD_Init();
    	LCD_Clear(Black);
    	LCD_SetBackColor(Black);
    	LCD_SetTextColor(White);
    	
    	
    	
    	
    	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
    	HAL_TIM_IC_Start_IT(&htim16, TIM_CHANNEL_1);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
    		lcd_show();
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    

    &&& 不要忘记了添加头文件!

    #include "headfile.h"
    

    fun.c函数
    具体逻辑,我现在看是蛮简单的,不管了,吃饭去了,自己悟去吧

    #include "headfile.h"
    
    char	text[20]; 
    
    uint32_t fre1, capture_value1, fre2, capture_value2 ;
    
    void lcd_show()
    {
    	sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·û
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	sprintf(text, "   R39_fre1:%d   ", fre1);
    	LCD_DisplayStringLine(Line2, (uint8_t *)text);
    	sprintf(text, "   R40_fre2:%d   ", fre2);
    	LCD_DisplayStringLine(Line4, (uint8_t *)text);
    	}
    
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	if(htim->Instance == TIM16)// R39
    	{
    		capture_value1 = TIM16->CCR1;
    		TIM16->CNT = 0;
    		fre1 = 80000000/(80*capture_value1);
    	
    	}
    	
    		if(htim->Instance == TIM2)//R40
    	{
    		capture_value2 = TIM2->CCR1;
    		TIM2->CNT = 0;
    		fre2 = 80000000/(80*capture_value2);
    	
    	}
    
    
    }
    
    

    ADC测量

    原理图

    通过R37和R38两个旋钮,测量AD的电压值

    cubemx配置

    分别对引脚PB15和PB12进行配置。

    keil代码

    记得在headfile.h文件中添加ADC头文件
    	在这里插入图片描述
    fun.c代码

    #include "headfile.h"
    
    
    
    
    char text[20];	
    void lcdshow()
    {
    	sprintf(text, "      zlfsgdsg      ");
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	
    	HAL_ADC_Start(&hadc1); 
    	uint32_t	adc_value =  HAL_ADC_GetValue(&hadc1); //R38
    	
    	sprintf(text, "     value:%d      ", adc_value);
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    
    }
    
    

    main.c
    记得将LCD初始化,然后在主函数中调用lcdshow();


    即可在lcd中实时读取adc1的值

    keil代码2
    若是要读取两个ad的电压值
    fun.c代码

    #include "headfile.h"
    
    
    
    
    char text[20];	
    void lcdshow()
    {
    	sprintf(text, "      zlfsgdsg      ");
    	LCD_DisplayStringLine(Line0, (uint8_t *)text);
    	
    	
    	sprintf(text, "     R37_volt:%.2f      ", get_vol(&hadc2));
    	LCD_DisplayStringLine(Line3, (uint8_t *)text);
    	
    	sprintf(text, "     R38_volt:%.2f      ", get_vol(&hadc1));
    	LCD_DisplayStringLine(Line5, (uint8_t *)text);
    
    }
    
    
    
    
    double get_vol(ADC_HandleTypeDef *hadc)
    {
    	
    	HAL_ADC_Start(hadc); 
    	uint32_t	adc_value =  HAL_ADC_GetValue(hadc); //R38
    	return	3.3*adc_value/4096; //因为AD是12位,所以ad最大值是4096
    
    }
    
    	
    
    

    fun.h

    void lcdshow(void);
    
    double get_vol(ADC_HandleTypeDef *hadc);
    

    串口发送和接收

    原理图

    cubemx配置


    keil代码

    串口发送
    main.c代码
    记得在前面添加头文件

      while (1)
      {
    		char text01[20];
    		sprintf(text01, "zlfsgdgs\r\n");
    		HAL_UART_Transmit(&huart1, (uint8_t *)text01, sizeof(text01), 50);
    		HAL_Delay(1000);
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    

    串口接收
    fun.c代码

    #include "headfile.h"
    
    uint8_t rec_data;
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart->Instance == USART1)
    	{
    		
    		HAL_UART_Transmit(huart, &rec_data, 1, 50);
    		
    		HAL_UART_Receive_IT(huart, &rec_data, 1);
    		
    	}
    
    
    }
    

    fun.h代码
    加一个外部变量定义

    extern uint8_t rec_data;
    

    main.c代码

    利用定时器进行串口不定长数据接收

    原理

    cubemx配置

    主要是把波特率设置为9600

    keil代码

    main.c
    把定时器使能!!!&&调用函数

    fun.c函数

    #include "headfile.h"
    
    char	send_buff[20];
    uint8_t rec_data, count;
    uint8_t	rec_flag;
    uint8_t	rec_buff[20];
    
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart->Instance == USART1)
    	{
    		
    		//HAL_UART_Transmit(huart, &rec_data, 1, 50);
    		TIM4->CNT = 0;
    		rec_flag = 1;
    		rec_buff[count]	= rec_data;
    		count ++;
    		HAL_UART_Receive_IT(huart, &rec_data, 1);
    		
    	}
    
    }
    
    void	uart_data_rec()
    {
    		if(rec_data)
    		{
    			if(TIM4->CNT > 15)
    			{
    				if(rec_buff[0] == 'z'	&& rec_buff[1] == 'l' && rec_buff[2] == 'f')
    				{
    					sprintf(send_buff, "zlf\r\n");
    					HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);
    				}
    				else if(rec_buff[3] == 's'	&& rec_buff[4] == 'g' && rec_buff[5] == 'd')
    				{
    					sprintf(send_buff, "sgd\r\n");
    					HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);
    				}
    				else if(rec_buff[6] == 's'	&& rec_buff[7] == 'g')
    				{
    					sprintf(send_buff, "sgd\r\n");
    					HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);
    				}
    				else
    				{
    					sprintf(send_buff, "error\r\n");
    					HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);
    				}
    				rec_flag = 0;
    				for(int	i=0; i<count; i++)
    					rec_buff[i] = 0;
    					count	= 0;
    			}
    		
    		}
    
    }
    	
    
    

    fun.h

    headfile.h
    要添加usart.h的头文件

    EEPROM读写

    原理

    原理就不说了,学嵌入式I2C的时候学了挺久

    keil代码

    i2c_hal_c

    void eeprom_write(uint8_t addr, uint8_t data)
    {
    	I2CStart();
    	I2CSendByte(0xa0);
    	I2CWaitAck();
    	I2CSendByte(addr);
    	I2CWaitAck();
    	I2CSendByte(data);
    	I2CWaitAck();
    	I2CStop();
    	
    	HAL_Delay(20);
    	
    }
    
    uint8_t eeprom_read(uint8_t addr)
    {
    	I2CStart();
    	I2CSendByte(0xa0);
    	I2CWaitAck();
    	I2CSendByte(addr);
    	I2CWaitAck();
    	I2CStop();
    	
    	I2CStart();
    	I2CSendByte(0xa1);
    	I2CWaitAck();
    	uint8_t data = I2CReceiveByte();
    	I2CSendNotAck();
    	I2CStop();
    	
    	return	data;
    }
    
    

    i2c_hal_h代码
    主要就是添加两个文件

    void eeprom_write(uint8_t addr, uint8_t data);
    uint8_t eeprom_read(uint8_t addr);
    

    main.c代码

    作者:土包子=-=

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯嵌入式学习攻略笔记

    发表回复