STM32F407之模拟I2C(二)之24C128

发布者:灵感狂舞最新更新时间:2018-05-20 来源: eefocus关键字:STM32F407  模拟I2C  24C128 手机看文章 扫描二维码
随时随地手机看文章

模拟I2C测试24C128的读写

#define GPIO_PORT_I2C GPIOH/* GPIO端口 */

#define I2C_SCL_PIN GPIO_Pin_4/* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN GPIO_Pin_5/* 连接到SDA数据线的GPIO */
/* 定义读写SCL和SDA的宏 */
#define I2C_SCL_1()  GPIO_PORT_I2C->BSRRL = I2C_SCL_PIN/* SCL = 1 */
#define I2C_SCL_0()  GPIO_PORT_I2C->BSRRH = I2C_SCL_PIN/* SCL = 0 */


#define I2C_SDA_1()  GPIO_PORT_I2C->BSRRL = I2C_SDA_PIN/* SDA = 1 */
#define I2C_SDA_0()  GPIO_PORT_I2C->BSRRH = I2C_SDA_PIN/* SDA = 0 */


#define I2C_SDA_READ()   GPIO_ReadInputDataBit(GPIOH,GPIO_Pin_5)/* 读SDA口线状态 */
#define I2C_SCL_READ()    GPIO_ReadInputDataBit(GPIOH,GPIO_Pin_4)/* 读SCL口线状态 */
/****************************************************************************************
*函 数 名:bsp_InitI2c
*函数功能:初始化i2c的io
*形    参:无
*返 回 值:无
*****************************************************************************************/
void bsp_InitI2c(void)
{
GPIO_InitTypeDef GPIO_initStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);

GPIO_initStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_initStructure.GPIO_OType = GPIO_OType_OD;
GPIO_initStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_initStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_initStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOH,&GPIO_initStructure);
}


/****************************************************************************************
*函 数 名:i2c_Delay
*函数功能:延时
*形    参:无
*返 回 值:无
*****************************************************************************************/
static void i2c_Delay(void)
{
uint8_t i=0;
for(i = 0; i < 30; i++);
}


/****************************************************************************************
*函 数 名:i2c_start
*函数功能:开始信号  
*形    参:无
*返 回 值:无
*****************************************************************************************/
void i2c_start(void)
{
I2C_SCL_0();/*SCL为高电平,SDA由高到低的跳变 就是开始信号*/
i2c_Delay();
I2C_SDA_1();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/****************************************************************************************
*函 数 名:i2c_stop
*函数功能:结束
*形    参:无
*返 回 值:无
*****************************************************************************************/
void i2c_stop(void)
{
I2C_SCL_0();/*SCL在高电平期间,SDA由低到高的跳变 就是停止信号*/
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/****************************************************************************************
*函 数 名:i2c_WaitAck
*函数功能:从器件应答
*形    参:无
*返 回 值:1 从器件应答
*****************************************************************************************/
uint8_t i2c_WaitAck(void)
{
uint8_t re;
uint16_t i=0;/*SCL为高电平 从器件把ASD拉低 称为从器件应答*/
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
while(I2C_SDA_READ() && (i < 65530))/*防止从器件不应答 在这死等*/
{
i++;
}
if(i < 65530)/*小于65530 表示已经应答   具体i的值是多少我也不知道 这里只是大概*/
re = 1;
else
re = 0;
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
return re;
}
/****************************************************************************************
*函 数 名:i2c_Ack
*函数功能:主器件应答
*形    参:无
*返 回 值:无
*****************************************************************************************/
void i2c_Ack(void)
{
I2C_SCL_0();/*SCL为高电平 SDA为低电平表示主器件应答*/
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/****************************************************************************************
*函 数 名:i2c_NAck
*函数功能:主器件不应答
*形    参:无
*返 回 值:无
*****************************************************************************************/
void i2c_NAck(void)
{
I2C_SCL_0();/*SCL为高电平 SDA为低电平表示主器件非应答*/
i2c_Delay();
I2C_SDA_1();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/****************************************************************************************
*函 数 名:i2c_SendByte
*函数功能:发送一个字节
*形    参:_ucByte 发送的字节
*返 回 值:无
*****************************************************************************************/
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
I2C_SCL_0();
for( i = 0; i < 8; i++)
{
if(_ucByte & 0x80)
I2C_SDA_1();
else
I2C_SDA_0();/*SCL上升沿将数据写入器件*/
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
_ucByte = _ucByte << 1;
}
I2C_SDA_1();/*释放数据线*/
i2c_Delay();

}
/****************************************************************************************
*函 数 名:i2c_ReadByte
*函数功能:读到的值
*形    参:无
*返 回 值:无
*****************************************************************************************/
uint8_t i2c_ReadByte(void)
{
uint8_t i;
uint8_t value = 0;
I2C_SDA_1();/*释放数据线*/
for(i = 0; i < 8; i++)
{
value <<=1;
I2C_SCL_1();
i2c_Delay();
if(I2C_SDA_READ())/*读SDA*/
{
value = value + 1;
}
else
{
value = value;
}
i2c_Delay();/*SCL下降沿将数据取出*/
I2C_SCL_0();
i2c_Delay();
}
return value;

}

/*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************                                                                      上面主要是模拟I2C时序                                                                                                                                                                    ************                                                                      下面就是对24C128的读写操作

*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/

#define EE_MODEL_NAME "AT24C128"
#define EE_DEV_ADDR 0xA0/* 设备地址 */
#define EE_PAGE_SIZE 64/* 页面大小(字节) */
#define EE_SIZE (16*1024)/* 总容量(字节) */
#define EE_ADDR_BYTES 2/* 地址字节个数 */


#define I2C_WR 0/* 写控制bit */
#define I2C_RD 1/* 读控制bit */

uint8_t buf[EE_SIZE];
/****************************************************************************************
*函 数 名:eeprom_ReadBytes
*函数功能:eeprom读字节
*形    参:_pReadBuf 存放读取的数据  _usAddress 开始读取的地址  _usSize读取的大小
*返 回 值:1 表示读取成功  0 表示读取失败
*****************************************************************************************/


uint8_t eeprom_ReadBytes(uint8_t *_pReadBuf,uint16_t _usAddress,uint16_t _usSize)
{
uint16_t i;
/*第一步:发起I2C启动信号*/
i2c_start();
/*第二步:发送控制字节,高7位表示地址,最低位表示读写控制 0表示写 1表示读*/
i2c_SendByte(EE_DEV_ADDR | I2C_WR);
/*第三步:等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
/*第四步:发送读取的地址 24C128 要发送2次地址*/
i2c_SendByte(_usAddress >> 8);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
/*发送读取的地址 */
i2c_SendByte(_usAddress);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
/*第五步:重启I2C总线  之后开始读取数据*/
i2c_start();
/*第六步:发送控制字节 */
i2c_SendByte(EE_DEV_ADDR | I2C_RD);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
/*第七步:循环读取数据*/
for(i = 0; i < _usSize; i++)
{
_pReadBuf[i] = i2c_ReadByte();/*读一个字节*/
if( i != _usSize -1)/*不是最后一个主器件就要应带,是最后一个就主器件非应答*/
{
i2c_Ack();
}
else
{
i2c_NAck();
}
}
/*第八步:发送I2C停止信号*/
i2c_stop();

return 1;

}
/****************************************************************************************
*函 数 名:eeprom_ReadTest
*函数功能:读取整个24C128的数据
*形    参:无
*返 回 值:无
*****************************************************************************************/
void eeprom_ReadTest(void)
{
uint16_t i;
int32_t Time1,Time2;
Time1 = bsp_GetRunTime();/*获取开始时间*/

if(eeprom_ReadBytes(buf,0,EE_SIZE))/*1 读取成功 0读取失败*/
{
Time2 = bsp_GetRunTime();/*获取结束时间*/
printf("读eeprom成功\r\n");
}
else
{
printf("读eeprom出错\r\n");
}

for(i = 0;i < EE_SIZE ;i++)
{

if(i % 16 == 0)/*输出16个字节换行*/
{
printf("\r\n");
}
printf(" %02X",buf[i]);/*输出数据*/

}
printf("读耗时: %dms,读速度: %dB/s\r\n",Time2 - Time1,(EE_SIZE * 1000) / (Time2 - Time1));


}


/****************************************************************************************
*函 数 名:eeprom_WriteBytes
*函数功能:写整个eeprom测试
*形    参:_pWriteBuf 写入的值  _usAddress 写入的地址 _usSize写入的大小
*返 回 值:1 表示写入成功 0 表示写入失败
*****************************************************************************************/
uint8_t eeprom_WriteBytes(uint8_t *_pWriteBuf,uint16_t _usAddress,uint16_t _usSize)
{
uint16_t i,m;
uint16_t usAddr;
uint16_t num = 0;
usAddr = _usAddress;

for( i = 0; i< _usSize; i++)
{
/*写eeprom不可以像读那样连续读取多个字节,写每次只能在一个页page
24C128每也64个字节*/
if (num % 64 == 0)/*写入64个就要重新开始 因为每page为64*/
{
/*第一步:发送停止信号,启动内部写操作*/
i2c_stop();
/*通过循环判断eeprom内部写操作是否完成*/
for(m = 0; m < 100; m++)
{
/*第二步:发起I2C总线启动信号*/
i2c_start();
/*第三步:发起控制字节,高7位是地址,最低位 0表示写 1表示读*/
i2c_SendByte(EE_DEV_ADDR | I2C_WR);
/*第四步:等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() == 1)
{
break;
}
if(m >= 100)/*大于100表示从器件没有应答*/
{
return 0;
}
}
/*第五步:发送写入的地址 24C128 要发送2次地址*/
i2c_SendByte(usAddr >> 8);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
/*发送写入的地址*/
i2c_SendByte(usAddr);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
}
/*第六步:写入数据*/
i2c_SendByte(_pWriteBuf[i]);
/*等待从器件应答 1表示应答 0 表示没有应带*/
if(i2c_WaitAck() != 1)
{
return 0;
}
num++;
usAddr++;/*地址增1*/
}
/*发送停止信号*/
i2c_stop();
return 1;
}


/****************************************************************************************
*函 数 名:eeprom_WriteTest
*函数功能:写入数据
*形    参:无
*返 回 值:无
*****************************************************************************************/


void eeprom_WriteTest(void)
{
uint16_t i;
int32_t Time1,Time2;

for(i = 0; i < EE_SIZE; i++)
{
buf[i] = 0x01;/*填充要写入的数据*/
}
Time1 = bsp_GetRunTime();/*获取开始时间*/

if(eeprom_WriteBytes(buf,0,EE_SIZE))/*1 表示写入成功 0表示失败*/
{
Time2 = bsp_GetRunTime();/*获取结束时间*/
printf("写eeprom成功\r\n");
}
else
{
printf("写eeprom错误\r\n");
}

printf("写耗时: %dms,写速度: %dB/s\r\n",Time2-Time1,(EE_SIZE *1000)/(Time2-Time1));
}


/*********************************************************************************************************************************************************************************************************************************************        下面就是Main函数   ********************************************************************************************************/


/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形    参:无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
uint8_t ch;
/*
ST固件库中的启动文件已经执行了 SystemInit() 函数,该函数在 system_stm32f4xx.c 文件,主要功能是
配置CPU系统的时钟,内部Flash访问时序,配置FSMC用于外部SRAM
*/
bsp_Init();/*初始化I2C的IO*/
/* 进入主程序循环体 */
printf("1 - 读EEPROM (%d 字节)\r\n", EE_SIZE);
printf("2 - 写EEPROM (%d 字节,0x00-0xFF)\r\n", EE_SIZE);
while (1)
{
if(comGetChar(COM1,&ch))/*读取串口数据*/
{
switch(ch)
{
case '1':
eeprom_ReadTest();/*测试读数据*/
printf("\r\n");
break;
case '2':
eeprom_WriteTest();/*测试写数据*/
printf("\r\n");
break;
default:
break;
}
}
}
}


关键字:STM32F407  模拟I2C  24C128 引用地址:STM32F407之模拟I2C(二)之24C128

上一篇:STM32F1使用I/0模拟I2C接口
下一篇:基于STM32F4移植W5500官方驱动库ioLibrary_Driver

推荐阅读最新更新时间:2024-03-16 16:03

51单片机模拟I2C总线的C语言实现
电路原理图     EEPROM为ATMEL公司的AT24C01A。单片机为ATMEL公司的AT89C51。   软件说明   C语言为Franklin C V3.2。将源程序另存为testi2c.c,用命令 C51testi2c.c L51TESTI2C.OBJ OHS51TESTI2C 编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。 3.源程序 #include reg51.h #include intrins.h #define uchar unsigned char #define uint unsigned
[单片机]
51单片机<font color='red'>模拟</font><font color='red'>I2C</font>总线的C语言实现
STM32F103 与 STM32F407引脚兼容问题
解决方案1: STM32F103有的功能407都有,并且这些功能的引脚完全兼容,只是程序不同而已。。。 而STM32F407有的功能103不一定有,因为407强大些。。。。。。希望对你有用 解决方案2: 不能。407支持摄像头,I2S等引脚,103都没有 解决方案3: 普通IO都一样,407有更多的附加功能。值得注意的是,407的电源引脚与103的有很大的区别,一定要注意!
[单片机]
基于 STM32F407 使用 4*4 矩阵键盘
写在前面: 这是我第一次开始写博客,可能写的不是很好,也请大家谅解。 本人现在大三,以前在学习过程中遇到过各种各样的问题,关于51单片机,STM32单片机,最近在学习ARM11的Tiny6410 以后还会更新一些C/C++/Qt等等方面的东西 关于写博客这件事,其实 一直想写博客记录下来,但是因为某些原因(懒),so , 没有写。现在开始,以后遇到单片机上或者编程上遇到的问题, 并且自己很好地解决了,我就会在这里记录下来。 希望通过博客记录我的学习历程并希望我所解决问题的过程能够帮到需要的人,一起加油吧!!! 我是在STM32F407开发板上使用的4*4 矩阵键盘 下面是我所使用的开发板 1、首先介绍一下4*4矩阵键盘扫
[单片机]
基于 <font color='red'>STM32F407</font> 使用 4*4 矩阵键盘
stm32f407之数字滤波(操作寄存器)
数字滤波 为了对stm32f4的ADC和DAC有更多的了解,我决定做一个实用性比较强的实验。就是数字滤波实验,利用stm32f4的DAC可以产生噪声的特点,利用它的一路DAC产生叠加噪声的信号作为原始信号。然后用ADC测量,把结果经过滤波处理后用DAC的另一通道把结果输出,用双踪示波器观察。 一阶惯性滤波器及其数字化 一阶惯性滤波器的传递函数为: 利用一阶差分法离散化,可以得到一阶惯性数字滤波算法: 其中T为采样周期,为滤波时间常数。T和必须根据信号频谱来选择。 编程实现: a. 设定一个1024点正弦波表,用DAC1叠加噪声输出 b. 配置定时器6更新频率为1M c. DAC
[单片机]
<font color='red'>stm32f407</font>之数字滤波(操作寄存器)
stm32F407的EXTI外部中断
要点:外部中断必须配置好EXTI和NVIC,因为要用的IO口做中断源,故IO的复用功能必须使能,F4的与其他的有些不同,它的外部中断复用功能是由SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOx,GPIO_PinSourcex); 进行配置的,当然,也要打开SYSCFG的时钟。 最让初学者头疼的就是中断服务函数的入口问题,一般的中断函数都会在stm32f4xx_it.h中声明,但是stm32f4xx_it.h只声明了一部分,自己需要的函数却没有定义,自己找了好久也没有找到,其实所有的中断函数入口都定义在了启动文件startup_stm32f4xx.s中。 /********************
[单片机]
关于stm32通信协议:软件模拟SPI、软件模拟I2C的总结
趁着帮老师代上嵌入式实验课的机会,又重新熟悉了一遍stm32的通信协议:串口协议、SPI协议、I2C协议、RS485协议。大概半年前,是过了一遍的,但也只停留于读了遍代码,跑了下例程,最近又过了一遍(自己仔细的看了一遍,老师还给我们讲了一遍,自己又讲了一遍),然后还写了一遍软件模拟SPI、软件模拟I2C的代码,才彻底的懂了个皮毛 ,:)。稍微总结下吧,总结的不好,都是自己的理解,仅供参考,主要说软件模拟SPI、I2C,硬件SPI和硬件I2C就不说了。 串口协议 串口协议没什么可说的,现在常用的串口协议,是基于以前的RS232的协议,因为RS232的引脚太多而改进过来的。 物理层只用三根引脚:TXD、RXD、GND(最好接,不然
[单片机]
【STM32】STM32F407 + DHT11
一、DHT11简介 DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~95%RH, 温度-20~+60℃。 ——来自百度百科 测量范围:湿度 5~95%RH, 温度 -20~+60℃ 测量精度:湿度 ±5%RH, 温度 ±2℃ 供电电压:3.3~5.5V DC 输 出:单总线数字信号 分辨率:湿度1%RH, 温度0.1℃ 关于单总线协议可以查看这篇文章:【STM32】stm32f407 + DS18B20 碰出不一样的火花 二、编程思路 温湿度传感器 DHT11 和 温度传感器 DS18B20 均采用 单总线协议,因此两者的编程思路很相似,不过 DHT11 增加了湿度
[单片机]
GPIO口模拟I2C
根据I2C通信规范(具体可以参考“ 浅谈I2C总线 ”),通过普通IO端口模拟可以实现单片机(主设备)与从设备的I2C通信,其中SCL通过IO口延时高低电平变化实现,SDA根据SCL状态变化产生开始信号,结束信号,以及实现发送接收数据等,以下是相关代码 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @Purpose: I2C Communication driver(By IO) * @Author: Purple * @Version: 1.0 * @Date: Create By Purple 2
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved