STM32学习

您所在的位置:网站首页 目录跑到下一页 STM32学习

STM32学习

2023-04-03 14:29| 来源: 网络整理| 查看: 265

一、认识IIC

二、EEPROM

          EEPROM==Electrically Erasable Programmable Read-Only Memory==电擦除可编程只读存储器。跟U盘差不多,可以存数据,电关掉数据还在。常见的型号24C02 、24C08、24C16

 C02表示2*1024 == 2K bit的存储大小

 C08表示8*1024 == 8K bit 的存储大小

C02每页可以存8个字节的数据;

C04、C08、C16每页可以存16个字节的数据;

大家应该都知道,存储器最小的存储单位是bit,一个字节(Byte)== 8bit;

可以想象EEPROM的一页,跟你写字的方格本是不是很像

24C02的一页

     每页8行8列,一行表示一个字节(Byte),每个小方格表示一个bit(一位)。24C02 EEPROM有32个像上面的页(page)。

24C02存储空间2k bit == 8bit *256;8bit就是上图的1行,2k就表示有256行,一行就是一个数据地址,所以24C02的数据地址分布是0x00 -- 0XFF

        24C02支持字节写模式和页写模式:

        字节写模式:就是一次写一个字节的数据,也就是8个bit的数据,也就是上图的一行。

        页写模式:就是一次写一页的数据,就是8个字节的数据。单不能跨页写数据,比如你一下子写9个字节的数据,那先在一页里面写8个数据,第9个数据就把第一个数据覆盖了,他不会自动跳到下一页去写。

EEPROM器件的设备地址和数据地址

设备地址可以理解为你们小区的地址,比如人民路88号;

数据地址可以理解为你家的门牌号,比如2幢801室;

因此可以把24C02看成一个小区,

一个小区有32幢房子,每个幢有8套房子,每套房子有8个房间。

24C02有32页,每页有8个字节的数据,每个字节有8个bit。

房子交易的最小单元是套吧,开发商应该不会只卖你一个房间吧?

同理24C02读写的最小单位也是1个字节。

24C02也支持整页写,就像你买房子,买一整幢也是可以的,但是不支持跨页写,如果涉及跨页,你可以一个字节一个字节的写

以下是用HAL库写的读写EEPROM

#include "i2c.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ I2C_HandleTypeDef hi2c1; /* I2C1 init function */ void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ } void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(i2cHandle->Instance==I2C1) { /* USER CODE BEGIN I2C1_MspInit 0 */ /* USER CODE END I2C1_MspInit 0 */ __HAL_RCC_GPIOB_CLK_ENABLE(); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* I2C1 clock enable */ __HAL_RCC_I2C1_CLK_ENABLE(); /* USER CODE BEGIN I2C1_MspInit 1 */ /* USER CODE END I2C1_MspInit 1 */ } } void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) { if(i2cHandle->Instance==I2C1) { /* USER CODE BEGIN I2C1_MspDeInit 0 */ /* USER CODE END I2C1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_I2C1_CLK_DISABLE(); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); /* USER CODE BEGIN I2C1_MspDeInit 1 */ /* USER CODE END I2C1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* * DevAddress: 24C02器件的地址 * MemAddress:寄存器地址 * pBuffer:要发送的数据指针 */ HAL_StatusTypeDef AT24C02_Write_OneBytes(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pBuffer) { HAL_StatusTypeDef Statu = HAL_OK; //调用HAL_I2C_Mem_Write函数在指定的寄存器地址写数据 Statu = HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pBuffer, 1, 10); //等待发送结束 while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY); //检查EEPROM是否准备好进行新的操作 while (HAL_I2C_IsDeviceReady(&hi2c1, DevAddress, 100, 100) != HAL_OK); //等待器件就绪,为下一次数据传输做准备,其实也不需要,因为HAL_I2C_Mem_Write函数里面有检测 while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY); return Statu; } //写多个字节,就是把写一个字节的函数,重复几遍 void AT24C02_Write_NBytes(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pBuffer, uint16_t Size) { uint16_t count = 0; for(count=0;count250) { SCL_L; return 1; } } SCL_L; return 0; }

发送一个字节的数据

void I2C_SendByte(uint8_t data) { uint8_t cnt; I2C_SDA_OUT(); for(cnt = 0; cnt < 8; cnt++) //分8次传输数据 一位一位传递 { SCL_L; Delay_us(5); if(data & 0x80) //先发最高位 { SDA_H; //写1 } else { SDA_L; //写0 } data = data


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3