电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
stm32f4标准库开发——at24c08驱动
分 享
扫描二维码分享
stm32f4标准库开发——at24c08驱动
STM32
eeprom
at24c08
Sixer
关注
发布时间: 2022-01-05
丨
阅读: 829
## stm32f4标准库开发——at24c08驱动 ### 主要概念: IIC总线:I2C 总线是一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。 IIC总线定义:时钟线:sck 数据线:sda 软件模拟:通过软件控制普通 GPIO 引脚高低点评切换,来模拟总线时序,从而达到与总线协议一样的效果。 eeprom:带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。 at24c08:8/8=1KByte 存储大小的eeprom。 ### 实验目的: 本实现通过软件模拟 IIC 来控制及读写 at24c08。 ### 硬件电路: 本实验的蜂鸣器为有源蜂鸣器 PB8 --> IIC_SCL PB9 --> IIC_SDA 在at24c08电路中,A0~A2都是接地的,这样AT24C08的地址就是 0xA0(A0~A2代表地址的后三位) ![](https://cf01.ickimg.com/bbsimages/202201/a618962fa633de47c87d0483c397bbdc.png) ![](https://cf01.ickimg.com/bbsimages/202201/b222a003719592199b4ce7900d477555.png) ### 主要库函数调用: ```c #define sda_in() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;} #define sda_out() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} #define iic_sda_out(x) PBout(9)=x #define iic_scl_out(x) PBout(8)=x #define iix_read_sda() PBin(9) ``` ### 代码: ```c //iic.c #include "iic.h" #include "base.h" #include "delay.h" //*********************************************************************** //移植修改部分 #define sda_in() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;} #define sda_out() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} #define iic_sda_out(x) PBout(9)=x #define iic_scl_out(x) PBout(8)=x #define iix_read_sda() PBin(9) static void iic_gpio_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); } static void iic_gpio_deinit(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); } //*********************************************************************** void iic_init(void) { iic_gpio_init(); iic_scl_out(1); iic_sda_out(1); } void iic_deinit(void) { iic_gpio_deinit(); iic_scl_out(1); iic_sda_out(1); } void iic_start(void) { sda_out(); iic_sda_out(1); iic_scl_out(1); delay_us(4); iic_sda_out(0); delay_us(4); iic_scl_out(0); } void iic_stop(void) { sda_out(); iic_scl_out(0); iic_sda_out(0); delay_us(4); iic_scl_out(1); iic_sda_out(1); delay_us(4); } uint8_t iic_wait_ack(void) { uint8_t ucerrtime = 0; sda_in(); iic_sda_out(1); delay_us(1); iic_scl_out(1); delay_us(1); while(iix_read_sda()) { ucerrtime++; if(ucerrtime > 250) { iic_stop(); return 1; } } iic_scl_out(0); return 0; } void iic_ack(void) { iic_scl_out(0); sda_out(); iic_sda_out(0); delay_us(2); iic_scl_out(1); delay_us(2); iic_scl_out(0); } void iic_nack(void) { iic_scl_out(0); sda_out(); iic_sda_out(1); delay_us(2); iic_scl_out(1); delay_us(2); iic_scl_out(0); } void iic_send_byte(uint8_t txd) { uint8_t t; sda_out(); iic_scl_out(0); for(t = 0; t < 8; t++) { iic_sda_out((txd & 0x80) >> 7); txd <<= 1; delay_us(2); iic_scl_out(1); delay_us(2); iic_scl_out(0); delay_us(2); } } uint8_t iic_read_byte(unsigned char ack) { unsigned char i, receive = 0; sda_in(); for(i = 0; i < 8; i++ ) { iic_scl_out(0); delay_us(2); iic_scl_out(1); receive <<= 1; if(iix_read_sda()) receive++; delay_us(1); } if (!ack) iic_nack(); else iic_ack(); return receive; } ``` ```c //iic.h #ifndef _IIC_H #define _IIC_H #include "stdint.h" void iic_init(void); void iic_deinit(void); void iic_start(void); void iic_stop(void); void iic_send_byte(uint8_t txd); uint8_t iic_read_byte(unsigned char ack); uint8_t iic_wait_ack(void); void iic_ack(void); void iic_nack(void); void iic_write_one_byte(uint8_t daddr, uint8_t addr, uint8_t data); uint8_t iic_read_one_byte(uint8_t daddr, uint8_t addr); #endif ``` ```c //at24cxx.c #include "24cxx.h" #include "stm32f4xx.h" #include "iic.h" #include "delay.h" eeprom_device_t at24cxx_dev = { .init = at24cxx_init, .wr = at24cxx_write, .rd = at24cxx_read, .type = AT24C02, }; void at24cxx_init(void) { iic_init(); } uint8_t at24cxx_read_one_byte(uint16_t read_addr) { uint8_t temp = 0; iic_start(); if(EE_TYPE > AT24C16) { iic_send_byte(0XA0); //发送写命令 iic_wait_ack(); iic_send_byte(read_addr >> 8); //发送高地址 } else iic_send_byte(0XA0 + ((read_addr / 256) << 1)); //发送器件地址0XA0,写数据 iic_wait_ack(); iic_send_byte(read_addr % 256); //发送低地址 iic_wait_ack(); iic_start(); iic_send_byte(0XA1); //进入接收模式 iic_wait_ack(); temp = iic_read_byte(0); iic_stop(); return temp; } void at24cxx_write_one_byte(uint16_t write_addr, uint8_t data_to_write) { iic_start(); if(EE_TYPE > AT24C16) { iic_send_byte(0XA0); //发送写命令 iic_wait_ack(); iic_send_byte(write_addr >> 8); //发送高地址 }else iic_send_byte(0XA0 + ((write_addr / 256) << 1)); //发送器件地址0XA0,写数据 iic_wait_ack(); iic_send_byte(write_addr % 256); //发送低地址 iic_wait_ack(); iic_send_byte(data_to_write); //发送字节 iic_wait_ack(); iic_stop(); delay_ms(10); } void at24cxx_write_len_byte(uint16_t write_addr, uint32_t data_to_write, uint8_t len) { uint8_t t; for(t = 0; t < len; t++) { at24cxx_write_one_byte(write_addr + t, (data_to_write >> (8 * t)) & 0xff); } } uint32_t at24cxx_read_len_byte(uint16_t read_addr, uint8_t len) { uint8_t t; uint32_t temp = 0; for(t = 0; t < len; t++) { temp <<= 8; temp += at24cxx_read_one_byte(read_addr + len - t - 1); } return temp; } uint8_t at24cxx_check(void) { uint8_t temp; temp = at24cxx_read_one_byte(255); //避免每次开机都写AT24CXX if(temp == 0x55) return 0; else { //排除第一次初始化的情况 at24cxx_write_one_byte(255, 0x55); temp=at24cxx_read_one_byte(255); if(temp == 0x55) return 0; } return 1; } void at24cxx_read(uint16_t read_addr, uint8_t *p_buffer, uint16_t Num_To_Read) { while(Num_To_Read) { *p_buffer++=at24cxx_read_one_byte(read_addr++); Num_To_Read--; } } void at24cxx_write(uint16_t write_addr,uint8_t *p_buffer,uint16_t num_to_write) { while(num_to_write--) { at24cxx_write_one_byte(write_addr, *p_buffer); write_addr++; p_buffer++; } } ``` ```c //at24cxx.h #ifndef _24CXX_H #define _24CXX_H #include "stdint.h" #define AT24C01 127 #define AT24C02 255 #define AT24C04 511 #define AT24C08 1023 #define AT24C16 2047 #define AT24C32 4095 #define AT24C64 8191 #define AT24C128 16383 #define AT24C256 32767 #define EE_TYPE AT24C02 typedef struct eeprom_device_s{ void (*init) (void); void (*wr) (uint16_t write_addr,uint8_t *p_buffer,uint16_t num_to_write); void (*rd) (uint16_t read_addr, uint8_t *p_buffer, uint16_t Num_To_Read); uint16_t type; }eeprom_device_t; extern eeprom_device_t at24cxx_dev; void at24cxx_init(void); uint8_t at24cxx_check(void); void at24cxx_read(uint16_t read_addr, uint8_t *p_buffer, uint16_t Num_To_Read); void at24cxx_write(uint16_t write_addr,uint8_t *p_buffer,uint16_t num_to_write); #endif ``` ```c //main.c #include "stm32f4xx.h" #include "delay.h" #include "usart.h" #include "stdio.h" #include "24cxx.h" uint8_t wr_data[128] = {0}; uint8_t rd_data[128] = {0}; int main(void) { uint8_t i = 0; delay_init(168); uart_init(115200); at24cxx_dev.init(); printf("write data !\r\n"); //向flash写入数据 for(i = 0; i < 128; i++) { wr_data[i] = i; } at24cxx_dev.wr(0, wr_data, 128); at24cxx_dev.rd(0, rd_data, 128); //从falsh读取数据并打印 printf("\r\nread data is :\r\n"); for(i = 0; i < 128; i++) { printf("%d, ", rd_data[i]); } while(1) { } } ``` ### 编译运行:result 如下,编译无报错,无警告。 ![](https://cf01.ickimg.com/bbsimages/202201/baf02a1878921c79e0f967f6580adb37.png) ### 实验现象: 实验借助串口打印来调试,可见成功写入并读取打印 eeprom 的数据。 ![](https://cf01.ickimg.com/bbsimages/202201/8088c61acd6d2cf1525e097f78a4da50.png) ### 总结: 理论上gpio操作加上精确的延时,能模拟出任何总线的时序。 构建的 eeprom_device_t 结构体类型,将eeprom设备看作一个对象,方便了函数管理及使用。 程序中的读写函数是一个一个读写的,eeprom其实是支持连续读写的,程序是可以继续改进的。 ### 工程下载: 关注公众号:InsertingAll 回复:PRJ1004006
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
Sixer
关注
评论
(1)
登录后可评论,请
登录
或
注册
Sixer
110
天前...
咋就没有人评论呢,呵呵
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交