野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13090|回复: 1

试着写了I2C的代码 为什么读取的时候总输出的是0XFF呢 本人新手望指教!

[复制链接]
发表于 2019-11-22 13:39:49 | 显示全部楼层 |阅读模式
是AT24C02

我的代码如下:

bsp_i2c.c文件
#include "bsp_i2c.h"

void I2C_EE_CONFIG(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        I2C_InitTypeDef I2C_InitStructure;
       
        //打开I2C的GPIO的Clock
        EEPROM_I2C_GPIO_APBxClkCmd(EEPROM_SCL_GPIO_CLK |EEPROM_SDA_GPIO_CLK ,ENABLE);//等同于 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       
        //打开I2C的外设的Clock
        EEPROM_I2C_APBxClkCmd(RCC_APB1Periph_I2C1,ENABLE);//等同于        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

        //配置I2C的GPIO的SCL引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);//配置到寄存器中
       
                //配置I2C的GPIO的SDA引脚
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_Init(GPIOB,&GPIO_InitStructure);//配置到寄存器中
       
        //配置I2C的工作模式
       
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;//使能应答
       
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//指定地址的长度
       
        I2C_InitStructure.I2C_ClockSpeed = EEPROM_I2C_BAUDRATE;  //配置时钟频率 单位是波特率
       
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;//配置时钟占空比
       
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
       
        I2C_InitStructure.I2C_OwnAddress1 = STM32_I2C_OWN_ADDR; //为7位地址 要和总线上的设备地址都不一样 这是STM32的IIC自身设备地址 总线上唯一即可
       
        I2C_Init(EEPROM_I2C,&I2C_InitStructure);//配置到寄存器中
       
       
        //使能I2C
        I2C_Cmd(EEPROM_I2C,ENABLE);
       
}

void EEPROM_Byte_Write(uint8_t addr,uint8_t data){//EEPROM的设备地址已经在里面默认了
        //发送起始信号
        I2C_GenerateSTART(I2C1,ENABLE);
        //检测EV5
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);//I2C_GetFlagStatus(I2C1,I2C_FLAG_SB);
        //发送设备地址
        I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
        //        EV8事件很普遍 所以只用EV6检测就可以
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR);//I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR);
        //发送要操作的EEPROM的存储单元地址
        I2C_SendData(I2C1,addr);
        //检测EV8事件
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR)//I2C_GetFlagStatus(I2C1,I2C_FLAG_TXE);
                //EV8事件被检测到 发送要存储的数据
        I2C_SendData(I2C1,data);
        //检测EV8_2事件 以便结束
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);
       
        //数据传输完成
        I2C_GenerateSTOP(I2C1,ENABLE);
               
        //
}

//等待EEPROM的处理好内部时序时用GET FLAG 真正的读取数据时还是要用事件Event
void EEPROM_WaitForWriteEnd(void)
{
        do{
        I2C_GenerateSTART(I2C1,ENABLE);
       
        while(I2C_GetFlagStatus(I2C1,I2C_FLAG_SB ) == RESET);
       
        I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
       
        }while(I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR) == RESET);

        I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
        }

        //从EEPROM读取数据

void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
{
        //产生起始信号
        I2C_GenerateSTART(EEPROM_I2C,ENABLE);
       
        while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
       
        //EV5事件被检测到,发送设备地址
        I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
       
  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);

        //EV6事件被检测到,发送要操作的存储单元地址
        I2C_SendData (EEPROM_I2C,addr);
       
        while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);

       
        //第二次起始信号
        //产生起始信号
        I2C_GenerateSTART(EEPROM_I2C,ENABLE);
       
        while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
       
        //EV5事件被检测到,发送设备地址
        I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);
       
  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR);


        while(numByteToRead)
        {
               
               
                //EV7事件被检测到       
                while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);

                //EV7事件被检测到,即数据寄存器有新的有效数据       
                *data = I2C_ReceiveData(EEPROM_I2C);
               
                if(numByteToRead == 1)
                {               
                        //如果为最后一个字节
                        I2C_AcknowledgeConfig (EEPROM_I2C,DISABLE);
                }               
               
                data++;
               
                numByteToRead--;
               
        }
       
       
        //数据传输完成
        I2C_GenerateSTOP(EEPROM_I2C,ENABLE);       
       
        //重新配置ACK使能,以便下次通讯
        I2C_AcknowledgeConfig (EEPROM_I2C,ENABLE);

}


//向EEPROM写入多个字节(页写入),每次写入不得超过8个字节
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite){

        I2C_GenerateSTART(I2C1,ENABLE);
       
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
         
        I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
       
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR);
       
        I2C_SendData(I2C1,addr);
       
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR);
       
        while(numByteToWrite){
               

        I2C_SendData(I2C1,*data);
       
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR);

       
        data++;
               
        numByteToWrite--;
        }
       
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)  == ERROR );
       
        I2C_GenerateSTOP(I2C1,ENABLE);
       
       
       

}

bsp_i2c.h文件
#ifndef __BSP_I2C_H
#define __BSP_I2C_H

#include "stm32f10x.h"
#include <stdio.h>
//EEPROM设备地址
#define EEPROM_ADDR                                         0xA0
//I2C地址
#define STM32_I2C_OWN_ADDR    0X5F//要和EEPROM设备地址不一样

//I2C EEPROM的引脚定义
#define EEPROM_I2C                    I2C1
#define EEPROM_I2C_CLK                                   RCC_APB1Periph_I2C1
#define EEPROM_I2C_APBxClkCmd                RCC_APB1PeriphClockCmd

#define EEPROM_I2C_BAUDRATE            400000

//IIC GPIO 引脚宏定义
#define EEPROM_SCL_GPIO_CLK         (RCC_APB2Periph_GPIOB)
#define EEPROM_SDA_GPIO_CLK   (RCC_APB2Periph_GPIOB)

#define EEPROM_I2C_GPIO_APBxClkCmd                        RCC_APB2PeriphClockCmd

#define EEPROM_I2C_SCL_GPIO_PORT   GPIOB
#define EEPROM_I2C_SCL_GPIO_PIN    GPIO_Pin_6

#define EEPROM_I2C_SDA_GPIO_PORT   GPIOB
#define EEPROM_I2C_SDA_GPIO_PIN    GPIO_Pin_7

void I2C_EE_CONFIG(void);
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
void EEPROM_WaitForWriteEnd(void);
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
#endif  /* __BSP_I2C_H */


main.c文件
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "./i2c/bsp_i2c.h"

//1.初始化I2C相关的GPIO
//2.配置I2C外设的工作模式
//3.编写I2C写入EEPROM的ByteWrite函数
//4.编写I2C读取EEPROM的RandomRead函数
//5.使用read函数及write函数进行读写校验
//6.编写pagewrite及seqread函数并使用 校验

/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */

uint8_t readData[10] = {0};
int main(void)
{       
        USART_Config();
        printf( "这是一个IIC通讯实验\n" );
       
        I2C_EE_CONFIG();
       
        EEPROM_Byte_Write(8,17);
        //这里必须加一个等待EEPROM处理自身内部时序的函数 由于STM32速度很快 外设速度慢 在写入字节过后 直接就读取的话会导致EEPROM由于正在处理自身内部时序而接受不到信号
        //所以要加一个循环重发信号的等待函数
        EEPROM_WaitForWriteEnd();
       
        EEPROM_Read(8,readData,1);
       
        printf("接受到的数据为0x%x",readData[0]);
       

        while (1)
        {
       
        }
}








TIM截图20191122133841.jpg
回复

使用道具 举报

发表于 2019-12-17 12:33:02 | 显示全部楼层
请问这个问题解决了吗?我也遇到了类似的问题。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-6-2 21:24 , Processed in 0.049398 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表