datasheet

基于STM32F103的GPIO模拟I2C操作AT24C02S-ST E2prom调试日志

2019-08-14来源: eefocus关键字:STM32F103  GPIO  模拟I2C  操作AT24C02

基于STM32F103的GPIO模拟I2C操作E2prom芯片AT24C02S-ST:



1、硬件环境初始化:Stm32管脚配置,管脚操作


typedef  struct _PIN_CFG

{

    GPIO_TypeDef *Port;

    uint16_t  Pin;

 

} PIN_CFG;

 

typedef  struct _E2PROM_CFG

{

    PIN_CFG SCL;

    PIN_CFG SDA;

} E2PROM_CFG;

 

E2PROM_CFG  E2prom_Cfg;

//初始化

void E2prom_Chip_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

 

    /*SCL*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    /*SDA*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    E2prom_Cfg.SCL.Port = GPIOB;

    E2prom_Cfg.SCL.Pin = GPIO_Pin_9;

 

    E2prom_Cfg.SDA.Port = GPIOB;

    E2prom_Cfg.SDA.Pin = GPIO_Pin_8;

 

 

    if(E2prom_Check() != TRUE)

    {

        System_State.bit_st  |= SYS_E2PROM;

        System_State.E2prom_St = FALSE;

    }

}

//SDA管脚控制

void E2prom_SDA_Set(uint8_t st)

{

    if(st == HIGH)

    {

        GPIO_SetBits(E2prom_Cfg.SDA.Port, E2prom_Cfg.SDA.Pin);

    }

    else

    {

        GPIO_ResetBits(E2prom_Cfg.SDA.Port, E2prom_Cfg.SDA.Pin);

    }

}

 

//SCL管脚控制

void E2prom_SCL_Set(uint8_t st)

{

    if(st == HIGH)

    {

        GPIO_SetBits(E2prom_Cfg.SCL.Port, E2prom_Cfg.SCL.Pin);

    }

    else

    {

        GPIO_ResetBits(E2prom_Cfg.SCL.Port, E2prom_Cfg.SCL.Pin);

    }

}

 

uint8_t E2prom_SDA_Get(void)

{

    return GPIO_ReadInputDataBit(E2prom_Cfg.SDA.Port, E2prom_Cfg.SDA.Pin);

}

 

2、模拟I2C接口:


//启动I2C

void E2prom_I2C_Start(void)

{

    E2prom_SDA_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(HIGH);

    DelayUs(5);

 

    E2prom_SDA_Set(LOW); /* 根据I2C总线定义: SCL为高时, 数据由高跳变至低表示开始信号 */

    DelayUs(5);

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

}

 

/* 产生I2C停止信号 */

void E2prom_I2C_Stop(void)

{

    E2prom_SDA_Set(LOW);

    DelayUs(5);

 

    E2prom_SCL_Set(HIGH);

    DelayUs(5);

 

    E2prom_SDA_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

}

//i2c发送一个字节

void E2prom_I2C_Send_Byte(uint8_t dat)

{

    uint8_t  i;

 

    for(i = 0; i < 8; i++)

    {

        E2prom_SCL_Set(LOW);

        DelayUs(5);

 

        if((dat & 0x80) == 0x80)

        {

            E2prom_SDA_Set(HIGH);

        }

        else

        {

            E2prom_SDA_Set(LOW);

        }

        dat <<= 1;

 

        E2prom_SCL_Set(HIGH);

        DelayUs(5);

    }

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

}

 

//i2c接收一个字节

uint8_t E2prom_I2C_Rcv_Byte(void)

{

    uint8_t  i;

    uint8_t  u8Temp = 0;

 

    E2prom_SDA_Set(HIGH);

 

    for(i = 0; i < 8; i++)

    {

        E2prom_SCL_Set(LOW);

        DelayUs(5);

 

        E2prom_SCL_Set(HIGH);

        DelayUs(5);

        u8Temp <<= 1;      //数据从高位开始读取

 

        if(E2prom_SDA_Get() == HIGH)

        {

            u8Temp++;

        }

    }

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

 

    return u8Temp;

}

//I2C主机应答

void E2prom_I2C_Ack(void)

{

    E2prom_SDA_Set(LOW);

    DelayUs(5);

 

    E2prom_SCL_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

}

//I2C主机无应答

void E2prom_I2C_NoAck(void)

{

    E2prom_SDA_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

}

//检测从机应答

uint8_t E2prom_I2C_Check_Ack(void)

{

    uint8_t u8Temp;

 

    E2prom_SDA_Set(HIGH);

    DelayUs(5);

 

    E2prom_SCL_Set(HIGH);

    DelayUs(5);

 

    if(E2prom_SDA_Get() == LOW)

        u8Temp = 1;

    else

        u8Temp = 0;

 

    E2prom_SCL_Set(LOW);

    DelayUs(5);

 

    return u8Temp;

}

3、E2prom读写


// e2prom指定地址写入一个字节

void E2prom_Write_Byte(uint32_t addr, uint8_t dat)

{

    uint8_t  u8Temp = 0;

 

    if(addr > 0xFFFF)

    {

        u8Temp = 0x08;

    }

 

    E2prom_I2C_Start();

    E2prom_I2C_Send_Byte(0xA0 + ((addr / 256) << 1));

    if(E2prom_I2C_Check_Ack() != 1)

    {

        u8Temp = 0;

        return;

    }

    E2prom_I2C_Send_Byte(addr % 256);

    if(E2prom_I2C_Check_Ack() != 1)

    {

        return;

    }

    E2prom_I2C_Send_Byte(dat);

    if(E2prom_I2C_Check_Ack() != 1)

    {

        return;

    }

 

    E2prom_I2C_Stop();

    DelayUs(20000);

}

 

//从e2prom指定地址读出一个字节

uint8_t E2prom_Read_Byte(uint32_t addr)

{

    uint8_t  u8Temp = 0;

 

    if(addr > 0xFFFF)

    {

        u8Temp = 0x08;

    }

 

    E2prom_I2C_Start();

    E2prom_I2C_Send_Byte(0xA0 + ((addr / 256) << 1));

    if(E2prom_I2C_Check_Ack() != 1)

    {

        return 0;

    }

 

    E2prom_I2C_Send_Byte(addr % 256);

    if(E2prom_I2C_Check_Ack() != 1)

    {

        return 0;

    }

 

    E2prom_I2C_Start();

    E2prom_I2C_Send_Byte(CTRL_CODE | u8Temp | 0x01);

    if(E2prom_I2C_Check_Ack() != 1)

    {

        return 0;

    }

 

    u8Temp = E2prom_I2C_Rcv_Byte();

 

    E2prom_I2C_NoAck();

    E2prom_I2C_Stop();

 

    return u8Temp;

}

 

//向e2prom指定地址写入多个字节

void E2prom_Write_Mult_Byte(uint32_t addr, uint8_t *pdat, uint8_t cnt)

{

    uint8_t  i;

 

    for(i = 0; i < cnt; i++)

    {

        E2prom_Write_Byte(addr++, *pdat++);

    }

}

 

// 从e2prom指定地址读出多个字节

void E2prom_Read_Mult_Byte(uint32_t addr, uint8_t *pdat, uint8_t cnt)

{

    uint8_t  i;

    for(i = 0; i < cnt; i++)

    {

        pdat[i] = E2prom_Read_Byte(addr++);

    }

}

 

//读写测试

uint8_t  E2prom_Check(void)

{

    uint8_t  test_buf[E2PROM_CHECK_SIZE], check_buf[E2PROM_CHECK_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xAA, 0x55 };

    memset(test_buf, 0, sizeof(test_buf));

    E2prom_Write_Mult_Byte(E2PROM_CHECK, check_buf, sizeof(check_buf));

    E2prom_Read_Mult_Byte(E2PROM_CHECK, test_buf, sizeof(test_buf));

    if(!memcmp(test_buf, check_buf, E2PROM_CHECK_SIZE))

        return TRUE;

    return FALSE;

}

调试中的问题;写入多个字节数据时,每写入后一个字节后至少10ms的延时,不能被其他线程打断,否则容易写入错误

关键字:STM32F103  GPIO  模拟I2C  操作AT24C02

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic471014.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32-(37):CAN总线(协议帧)
下一篇:STM32 IO口模拟I2C+驱动MPU6050

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

基于stm32f103的矩阵键盘

我现在的任务是做一个8*8的矩阵键盘,制PCB版之前,我用电路板搭了一个3*3的矩阵键盘来模拟一下,设置PA0、PA1、PA2为PP输出,设置P3、P4、P5下拉输入。大多数的芯片内部上拉或下拉电阻都是弱上拉或弱下拉,stm32f103的内部也一样,内部上拉或下拉的电阻阻值约为40K,这样可以方便外部调整,但是,在作为一些通讯引脚时,可能会出现上电时数据不稳定的问题,如I2C通讯,解决的办法是在外部在加上一个较强的上拉或下拉即可。具体程序如下:#include <stm32f10x.h>#include "usart.h"void KeyBoard_Init(void)//按键初始化
发表于 2019-08-16

基于 STM32F407 使用 4*4 矩阵键盘

写在前面:这是我第一次开始写博客,可能写的不是很好,也请大家谅解。本人现在大三,以前在学习过程中遇到过各种各样的问题,关于51单片机,STM32单片机,最近在学习ARM11的Tiny6410以后还会更新一些C/C++/Qt等等方面的东西关于写博客这件事,其实 一直想写博客记录下来,但是因为某些原因(懒),so , 没有写。现在开始,以后遇到单片机上或者编程上遇到的问题,并且自己很好地解决了,我就会在这里记录下来。希望通过博客记录我的学习历程并希望我所解决问题的过程能够帮到需要的人,一起加油吧!!!我是在STM32F407开发板上使用的4*4 矩阵键盘下面是我所使用的开发板1、首先介绍一下4*4矩阵键盘扫描原理 
发表于 2019-08-16
基于 STM32F407 使用 4*4 矩阵键盘

基于STM32F407最小系统板三种矩阵键盘实现方法

0xe0:return 0xe7; case 0xd0:return 0xd7; case 0xb0:return 0xb7; case 0x70:return 0x77; } } if(mode) key =1; if((GPIO_ReadInputData(GPIOA)&0xF0)==0xF0) key =1; return 0;}比较:三种方案其实,第二种方案比较通用,第一种比较简单易懂,前两种都比较好,因为按键按下不松开,并不会影响CPU一直停留在while()循环里啥都不干。最后的实验效果:之前用的板子是STM32F107,数据手册中的GPIO口一些输出输入方式的配置与STM32F
发表于 2019-08-16
基于STM32F407最小系统板三种矩阵键盘实现方法

STM32F103——4*4矩阵扫描(极简事件扫描,非主延时)

:设置IO为推挽输出// 输入:port, pin按位(可为组合)void IoDirOutput(GPIO_TypeDef* port, uint16_t pin){    GPIO_InitTypeDef GPIO_InitStructure;    GPIO_InitStructure.GPIO_Pin   = pin;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_InitSt
发表于 2019-08-16

关于STM32F103型号的矩阵按键的程序书写

最近参加电子大赛要写一个矩阵按键,刚开始写了好长时间换了好几个矩阵按键都不好使,但是 我感觉我的程序和原理都没有错,调试了好久也没有发现问题在哪?我按照我自己的思路把程序重写了一遍bug消失了,程序很好的运行。程序贴出来,纪念一下。#include "keypad.h"#include "stm32f10x.h"#include "delay.h"
发表于 2019-08-16

HAL库之485+DMA通信(STM32F746)

(uint32_t num){ while(num--);} void RS485_Send_data(uint8_t *pdata,uint16_t data_size){ RS485_T; delay485(4); while(HAL_UART_GetState(&huart2)!=HAL_UART_STATE_READY); HAL_UART_Transmit_DMA(&huart2,pdata,data_size); while(HAL_UART_GetState(&huart2)!=HAL_UART_STATE_READY); RS485_R; delay485(4);} void
发表于 2019-08-16
HAL库之485+DMA通信(STM32F746)

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved