蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

这篇具有很好参考价值的文章主要介绍了蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言:

IIC协议简介:

1、起始信号和停止信号:

2、应答信号:

3、读写字节:

AT24C02:

字节写操作:

页写操作:

读操作:

MCP4017:

写操作:

读操作:


前言:

        本篇文章主要介绍IIC通信协议,同时给大家介绍一下蓝桥杯嵌入式的模块的AT24C02和MCP4017,此外本篇博客会采用按键控制PB14来读取可编程电阻MCP分的电压值,并将电压值存储在AT24C02中。

IIC协议简介:

        I2C(IIC,Inter-Integrated Circuit), 一种半双工通信协议,采用两线式串行总线, 它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,这两条线必须通过上拉电阻连接正电源。数据传输只能在总线不忙时启动。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

        对于STM32来说,G4系列的芯片自带3个硬件IIC,而对于我们的比赛来说,官方为我们提供的代码采用的不是硬件上的IIC,而是使用PB6 和 PB7这两个IO口来模拟IIC的进程。接下来我会结合蓝桥杯嵌入式为大家提供的参考代码来为大家讲解一下IIC通信的一些操作。

1、起始信号和停止信号:

        下图是IIC起始和停止时序图,起始和停止均由主机来发出,IIC总线在主机发出起始信号后处于忙碌状态,而在主机发出停止信号后,总线处于空闲状态(I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高)。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

        

        起始条件:在SCL保持为高电平的情况下,SDA出现一个下降沿,对应代码部分为:

void I2CStart(void)
{
    SDA_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SDA_Output(0);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);
}

        停止条件:在SCL保持为高电平的情况下,SDA出现一个上升沿,对应代码部分为:

void I2CStop(void)
{
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output(0);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SDA_Output(1);
    delay1(DELAY_TIME);

}

2、应答信号:

        每当主机向从机发送完一个字节的数据,主机总是需要等待从机发出一个应答信号,以检验从机是否成功接收到了数据。

        下面就是应答时序图,只有在DATA OUT 被置为低的时候,才会被认为是从机产生应答,否则被认为是不应答。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         等待从机发送应答对应代码部分:

unsigned char I2CWaitAck(void)
{
    unsigned short cErrTime = 5;
    SDA_Input_Mode();
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    while(SDA_Input())
    {
        cErrTime--;
        delay1(DELAY_TIME);
        if (0 == cErrTime)
        {
            SDA_Output_Mode();
            I2CStop();
            return ERROR;
        }
    }
    SDA_Output_Mode();
    SCL_Output(0);
    delay1(DELAY_TIME);
    return SUCCESS;
}

        主从机发送应答或者非应答对应代码:

/**
  * @brief I2C发送确认信号
  * @param None
  * @retval None
  */
void I2CSendAck(void)
{
    SDA_Output(0);
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);

}

/**
  * @brief I2C发送非确认信号
  * @param None
  * @retval None
  */
void I2CSendNotAck(void)
{
    SDA_Output(1);
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);

}

3、读写字节:

        在介绍读写字节前,我要给大家强调一点,数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变),只有当SCL被拉低后,SDA才能被改变在SCL为高电平期间(有效数据时间段),发送数据,发送8次数据,如果数据为1,显然SDA是被拉高;如果数据为0,那么SDA被拉低

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         对于IIC协议来说,传输到SDA上的数据必须是八位,在数据传输的时候,先传输数据的最高位,再传输数据的最低位,也就是嵌入式工程师所说的高位先行(MSB),每当有一个字节的数据发送后,必须发送一位应答位,总的数据就是8位数据加1位应答,也就是说一帧有9位数据。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         读写操作对应的代码部分:

/**
  * @brief I2C发送一个字节
  * @param cSendByte 需要发送的字节
  * @retval None
  */
void I2CSendByte(unsigned char cSendByte)
{
    unsigned char  i = 8;
    while (i--)
    {
        SCL_Output(0);
        delay1(DELAY_TIME);
        SDA_Output(cSendByte & 0x80);
        delay1(DELAY_TIME);
        cSendByte += cSendByte;
        delay1(DELAY_TIME);
        SCL_Output(1);
        delay1(DELAY_TIME);
    }
    SCL_Output(0);
    delay1(DELAY_TIME);
}

/**
  * @brief I2C接收一个字节
  * @param None
  * @retval 接收到的字节
  */
unsigned char I2CReceiveByte(void)
{
    unsigned char i = 8;
    unsigned char cR_Byte = 0;
    SDA_Input_Mode();
    while (i--)
    {
        cR_Byte += cR_Byte;
        SCL_Output(0);
        delay1(DELAY_TIME);
        delay1(DELAY_TIME);
        SCL_Output(1);
        delay1(DELAY_TIME);
        cR_Byte |=  SDA_Input();
    }
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output_Mode();
    return cR_Byte;
}

        这里我要给大家解释一点代码,SDA_Output(cSendByte & 0x80);

        函数每次接收过来的都是一个字节,而通过&0x80就会保留最高位的数据,舍弃后七位的数据,也就是说,通过这个操作之后,就只有1位数据被保存了下来,然后通过cSendByte += cSendByte;将这一位数据进行加法计算,这可以看作是这一位数据的左移运算。同样的道理也适用于cR_Byte += cR_Byte;cR_Byte |=  SDA_Input();这两句代码。

AT24C02:

        AT24C02是一款2K容量的串行电可擦除只读存储器,内部包含256个字节,每个字节8位。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         在官方给出的原理图上,AT24C02和MCP4017被挂载在了PB6 PB7两个接口上,也就以为着,AT24C02是做为从机来跟单片机进行通信的。这就要求我们去看一下数据手册,找到其从机地址。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         手册中的地址前4位是固定不变的,后3位是可以根据电平的高低来决定,最后一位由开发者决定是对其进行读操作还是写操作来决定最后一位的数据是0还是1。而开发板将A2 A1 A0全部接地,这就决定了我们如果用读操作就是0xA1,写操作就是0xA0;

字节写操作:

        蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         字节写操作需要由单片机发出起始状态和器件地址,紧跟着给出一个8位数据地址。一经收到该地址,AT24C02就立刻发送应答,并随时钟输入8位数据。在收到8位数据之后,AT24C02再次发送应答,单片机发送停止信号来终止写操作。同时,这里要注意的是AT24C02每次写完内容后会自动指向下一个内存空间。但是这里一定要延时一下,这样才能保证写入的正确

        AT24C02写操作对应代码部分:

void EEPROM_write(unsigned char address,unsigned char data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();
	I2CSendByte(data);
	I2CWaitAck();
	I2CStop();//停止IIC
    HAL_Delay(5);
}

页写操作:

        蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         AT24C02能进行8字节页面写入,04、08和16系列设备能进行16字节页面写入。激发写页面与激发写字节相同,只是数据传送设备无须在第一个字节随时钟输入之后,发出一个停止状态。在EEPROM确认收到第一个数据之后,数据传送设备能再传送7个(1KB、2KB)或15个(4KB、8KB、16KB)数据,每一个数据收到之后,EEPROM都将通过SDA回送一个确认信号,最后数据传送设备必须通过停止状态终止页面写序列。

        页写操作对应代码部分:

void EEPROM_pagewrite(unsigned char *pageBuf,unsigned char address,unsigned char num)
{
    I2CStart();
    I2CSendByte(0xa0); // 器件地址
    I2CWaitAck();
    
    I2CSendByte(address);  // 写数据地址
    I2CWaitAck();
    
    while(num--)
    {
        I2CSendByte(*pageBuf++);
        I2CWaitAck();
    }
    I2CStop();
    delay1(500);
}

读操作:

        读取操作分为三种,分别是当前地址读取,一个是随机读取,另一个是顺序读取。这里给大家介绍一下随机读取,随机读取的时序图如下所示。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         先由主机发送一个起始信号,紧接着再发送器件地址(0xa0),等待从机响应,然后发送读取的地址,等待从机响应,之后再次发送起始信号,这时候发送的器件地址就是0xa1了,等待从机回应之后,然后才开始数据读取,每次进行数据读取后,需要进行等待响应操作,如果收到的响应是不响应,那么这时候发送停止信号,代表着读取结束。

unsigned char EEPROM_read(unsigned char address)
{
	unsigned char dat;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();

	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	dat = I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	return dat;
}

MCP4017:

        MCP4017是一款可编程的电阻,其内置了7位寄存器,共计127个档位的分辨率。在蓝桥杯嵌入式比赛中,MCP4017同样放在了PB6 PB7 两个IO上,我们可以用IIC总线来跟他通信。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         对于蓝桥杯嵌入式比赛来说,采用的是MCP4017T-104ELT,也就是说他的最大电阻达到了100K。

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         通过这张图,我们可以清晰的看出,随着我们向MCP中输入的数越大,他对应的电阻也就越大,当我们传入0x7f时,对应的电阻就是100K。这里要注意的一点是,我们写进去的一个数字(0-127),读出来也是一个数字,转化为电阻阻值:R = 787.4 * read_resistor 欧,电压:3.3*(R/(R+10)) (假设外接的电压为3.3)

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         通过阅读数据手册,我们可以得到MCP4017的从机地址,如果是读操作的话就是0x5f,写操作的话就是0X5E。接下来,我们根据时序图来编写MCP的读写操作。

写操作:

        蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         这个就比AT24C02好看多了,先发送起始信号,等待响应,发送数据,等待响应,结束信号,一个写操作就结束了。对应代码部分如下:

void MCP4017_write(unsigned char value)
{
	I2CStart();
	I2CSendByte(0x5e);
	I2CWaitAck();
	I2CSendByte(value);
	I2CWaitAck();
	I2CStop();
	
}

读操作:

        蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

         这里需要注意的一点是主设备负责发起响应和响应信号。如果出现响应信号,MCP4017将中止此传输并释放总线。

        读取操作对应的代码部分:

unsigned char  MCP4017_read(void)
{
	unsigned char value;
	
	I2CStart();
	I2CSendByte(0x5f);
	I2CWaitAck();
	value = I2CReceiveByte();
	I2CSendNotAck();
	I2CStop();
	
	return value;
}

按键控制PB14读取可编程电阻MCP分得电压,并将电压值存储在AT24C02中:

        写好的按键工程                                                                                提取码:2471

        大家可以在我这个按键工程的基础上进行修改。

        通过开发板上的B2 B3 B4个按键,来分别控制MCP4017不同的电阻值,同时利用B1来显示上一次存储到AT24C02中的电压。

        1、将PB6 PB7设定为推挽输出

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

2、设定PB14为ADC通道,并完成相关配置

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

 蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

Resolution:ADC采样的分辨率这里直接默认选择12位的精度就可以了,如输入电压为0-3.3V,12位,即0V对应0,3.3V对应2^12-1=4095,通过这个转换我们就可以算出对应的电压值。
Rank:采样间隔设置我们这里选择默认2.5就行了,间隔越小采样频率越高。 之后,咱们的Cubemx的配置就算基本完成了,点击generate生成代码即可。不过要记得把官方提供的i2c_hal.c和i2c_hal.h加入我们的工程。

        打开工程后,在i2c_hal.c里面添加AT24C02和MCP4017的代码,并且在.h文件中声明一下

AD采集对应的代码:

unsigned int adc_val;
float vol;
void Get_vol()
{
	HAL_ADC_Start(&hadc1);
	adc_val = HAL_ADC_GetValue(&hadc1);
	vol = adc_val/4096.0f * 3.3f;
}

主函数对应的代码:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#include "lcd.h"
//#include "fonts.h"
#include "interrupt.h"
#include "stdio.h"
#include "i2c_hal.h"

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
char text[20];
extern unsigned int TIM3_count;
extern struct keys key[4];

unsigned char TIM3_count_H;
unsigned char TIM3_count_L;
unsigned int  EEPROM_temp;
unsigned char res_4017;
unsigned int PB14_ADC;
float volt1;

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	HAL_TIM_Base_Start_IT(&htim3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_ADC_Start(&hadc1);
		PB14_ADC = HAL_ADC_GetValue(&hadc1);
		volt1 = PB14_ADC * 3.5/4096;
		sprintf(text,"Now time_value:%d",TIM3_count);
		LCD_DisplayStringLine(Line4 ,(unsigned char *)text);
		EEPROM_temp = (EEPROM_read(0x00)<<8)+EEPROM_read(0x01);
		sprintf(text,"EEPROM_temp:%d",EEPROM_temp);
		LCD_DisplayStringLine(Line1 ,(unsigned char *)text);
		sprintf(text,"RES %5.4fK",res_4017*0.7874);
		LCD_DisplayStringLine(Line6,(uint8_t *)text);
		sprintf(text,"Vol %5.4fV",3.3*res_4017*0.7874/(res_4017*0.7874 + 10));
		LCD_DisplayStringLine(Line3, (unsigned char *)text);
		sprintf(text,"ture %5.4fV",volt1);
//		sprintf(text,"ture %d",PB14_ADC);
		LCD_DisplayStringLine(Line7, (unsigned char *)text);
		if(key[0].single_flag == 1)
		{
			sprintf(text,"key0down");
			LCD_DisplayStringLine(Line8,(uint8_t *)text);
			MCP4017_write(0x00);
			res_4017 = MCP4017_read();
			key[0].single_flag = 0;
		}
		else if(key[1].single_flag == 1)
		{
			sprintf(text,"key1down");
			LCD_DisplayStringLine(Line8,(uint8_t *)text);
			MCP4017_write(0x0d);
			res_4017 = MCP4017_read();
			key[1].single_flag = 0;
		}
		else if(key[2].single_flag == 1)
		{
			sprintf(text,"key2down");
			LCD_DisplayStringLine(Line8,(uint8_t *)text);
			key[2].single_flag = 0;
			MCP4017_write(0x40);
			res_4017 = MCP4017_read();
		}
		else if(key[3].single_flag == 1)
		{
			TIM3_count_H = TIM3_count >> 8;
			TIM3_count_L = TIM3_count & 0xff;
			EEPROM_write(0x00,TIM3_count_H);
			HAL_Delay(10);					//写入需要时间,延时是为了给写操作留出时间
			EEPROM_write(0x01,TIM3_count_L);
			HAL_Delay(10);
			sprintf(text,"key3down");
			MCP4017_write(0x7f);
			res_4017 = MCP4017_read();
			LCD_DisplayStringLine(Line8,(uint8_t *)text);
			key[3].single_flag = 0;
		}
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

最终代码实现:

最终代码                                                                                                                提取码:2471文章来源地址https://www.toymoban.com/news/detail-406086.html

到了这里,关于蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧,说起来很简单,就是几行代码的事,但楞是折腾了我大半天时间才搞定。原因后面说,先看代码吧: 读操作很简单,以32位方式读取的时候是这样的: 需要注意的是,当以32位方式读取时,地址需要是4的整数倍,即32位。 8位或16位方式类似操作即可 需要注意的

    2024年01月18日
    浏览(67)
  • 嵌入式Linux裸机开发(七)UART串口、IIC、SPI通信

    大概学完这三种通信后,之后就先去学系统移植,其他的先暂时放下 串口全称叫做串行接口,通常也叫做 COM 接口。 UART:(Universal Asynchronous Receiver/Trasmitter)通用异步串行收发器。 USART:(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行收发器,相比 UART多了

    2024年02月07日
    浏览(74)
  • 【蓝桥杯嵌入式】蓝桥杯嵌入式第十二届省赛题,考点:模拟电压,串口通信,计时器

     🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏 🎏【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 🎏【蓝桥杯嵌入式】蓝桥杯第十二届省赛程序真题 🎏【蓝桥杯嵌入式

    2023年04月09日
    浏览(72)
  • STM32G431RB--基于HAL库(蓝桥杯嵌入式赛前梳理)

    明天就进行蓝桥杯的比赛了,最后一天再重新梳理一下各个模块的使用和代码的编写。 如果各个模块的MX配置是根据我之前发的来的,那么这篇文章中的代码完全适用;如不是,原理部分也是相同的,代码部分适用,可以自行判断,作为一个参考。 引脚: 1.控制LED灯亮灭时需

    2023年04月08日
    浏览(91)
  • 蓝桥杯嵌入式STM32 G431 hal库开发速成——ADC与DAC

    模数转换器(ADC):它将模拟信号转换为单片机能够处理的数字信号。在很多应用中,比如温度传感器、压力传感器等,信号最初都是模拟形式的。ADC 读取这些模拟信号,然后将它们转换为数字形式,以便单片机可以读取和处理。 数模转换器(DAC):它执行相反的操作,将

    2024年02月01日
    浏览(59)
  • SPI、UART、RS232、RS485、IIC 5种嵌入式经典通信总线协议

      UART即通用异步收发器,是一种通用的串行、异步通信总线。该总线有两条数据线,可以实现全双工的发送和接收。在嵌入式系统种常用于主机与辅助设备之间的通信。UART就是串口,也是一种通信协议/总线协议。 电脑上已经逐步没有了,换成了usb,但是在嵌入式领域是最

    2024年01月16日
    浏览(55)
  • 第十三届蓝桥杯嵌入式国赛真题(基于HAL库的巨简代码+超级详解)

    相关说明: 开发板:CT117E-M4(STM32G431RBT6) 开发环境: CubeMX+Keil5 涉及题目:第十三届蓝桥杯嵌入式国赛真题 难点:双路AD测量电压、输入捕获测频率、LCD屏幕翻转、冒泡法、初始上电判断、按键长短按 CubeMX配置、主要函数代码及说明: 1.使能外部高速时钟: 2.配置时钟树:

    2023年04月09日
    浏览(68)
  • 第十三届蓝桥杯嵌入式省赛第二场真题(基于HAL库的巨简代码+超级详解)

    相关说明: 开发板:CT117E-M4(STM32G431RBT6) 开发环境: CubeMX+Keil5 涉及题目:第十三届蓝桥杯嵌入式省赛第二场真题 CubeMX配置、主要函数代码及说明: 1.使能外部高速时钟: 2.配置时钟树: 3.GPIO: 4.TIM2(通道2 PA1输出脉冲信号): 5.UART: 6.NVIC优先级配置    博主参加的是第一场

    2023年04月09日
    浏览(57)
  • 第十二届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

    相关说明: 开发板:CT117E-M4(STM32G431RBT6) 开发环境: CubeMX+Keil5 涉及题目:第十二届蓝桥杯嵌入式省赛第一场真题 技巧:字符串比较 、字符串数组转移提取、for和return搭配使用、goto语句、利用%c和%s打印 CubeMX配置、主要函数代码及说明: 1.使能外部高速时钟: 2.配置时钟树:

    2023年04月11日
    浏览(44)
  • 蓝桥杯嵌入式STM32G431RBT6的学习(总大纲)(HAL库学习)板子介绍

    我写蓝桥杯嵌入式大概用到的外设,都是非常常用的。我在这里汇总一下。 蓝桥杯嵌入式基础模块——GPIO的使用(新板)STM32G431(HAL库开发)_薛定谔的猫咪死了的博客-CSDN博客 蓝桥杯嵌入式基础模块——串口的使用(新板)STM32G431(HAL库开发)_薛定谔的猫咪死了的博客-C

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包