BSRR = GPIO_Pin_6) define SCL_L (GPIOB->BRR = GPIO_Pin_6" />
历史上的今天
返回首页

历史上的今天

今天是:2025年03月08日(星期六)

2019年03月08日 | STM32之I2C例程(24C02)

2019-03-08 来源:eefocus

#include "stm32f10x.h"

#include


#define SCL_H  (GPIOB->BSRR = GPIO_Pin_6)

#define SCL_L  (GPIOB->BRR = GPIO_Pin_6)

#define SDA_H  (GPIOB->BSRR = GPIO_Pin_7)

#define SDA_L  (GPIOB->BRR = GPIO_Pin_7)

#define SCL_READ (GPIOB->IDR & GPIO_Pin_6)

#define SDA_READ (GPIOB->IDR & GPIO_Pin_7)

#define I2C_DELAY (I2C_delay())


/* RCC时钟配置 */

void RCC_config(void)

 ErrorStatus HSEStartUpStatus;


 /* RCC寄存器设置为默认配置 */

 RCC_DeInit();

 /* 打开外部高速时钟 */

 RCC_HSEConfig(RCC_HSE_ON);

 /* 等待外部高速时钟稳定 */

 HSEStartUpStatus = RCC_WaitForHSEStartUp();

 if(HSEStartUpStatus == SUCCESS) 

 { 

  /* 设置HCLK = SYSCLK */

  RCC_HCLKConfig(RCC_SYSCLK_Div1);

  /* 设置PCLK2 = HCLK */

  RCC_PCLK2Config(RCC_HCLK_Div1);

  /* 设置PCLK1 = HCLK / 2 */

  RCC_PCLK1Config(RCC_HCLK_Div2);

//  /* 设置FLASH代码延时 */

//  FLASH_SetLatency(FLASH_Latency_2);

//  /* 使能预取址缓存 */

//  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

  /* 设置PLL时钟源为HSE倍频9 72MHz */

  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

  /* 使能PLL */

  RCC_PLLCmd(ENABLE);

  /* 等待PLL稳定 */

  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

  /* 设置PLL为系统时钟源 */

  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

  /* 等待系统时钟源切换到PLL */

  while(RCC_GetSYSCLKSource() != 0x08);

 }

}


/* GPIO配置 */

void GPIO_config(void)

{

 GPIO_InitTypeDef GPIO_InitStructure;


 /* 时钟配置 */

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);


 /* SDA、SCL开漏输出 */

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

}


/* 毫秒延时函数 */

void delay_ms(uint16_t time)

{    

 uint16_t i = 0; 


 while(time--)

 {

  i = 12000;

  while(i--);    

 }

}


/* I2C延时函数 */

void I2C_delay(void)  

{     

 uint8_t i = 100;  


 while(i)   

 {      

  i--;   

 }

}


/* I2C开始信号 */

bool I2C_Start(void)  

{

 SDA_H;

 SCL_H;

 I2C_DELAY;

 if(!SDA_READ)  

  return false;

 

 SDA_L;

 I2C_DELAY;  

 if(SDA_READ)   

  return false;

 

 SDA_L;

 I2C_DELAY;

 

 return true;  


/* I2C停止信号 */

void I2C_Stop(void)

{

 SCL_L;

 I2C_DELAY;

 SDA_L;

 I2C_DELAY;

 SCL_H;

 I2C_DELAY;

 SDA_H;

 I2C_DELAY;

}


/* I2C响应信号 */

void I2C_Ack(void)  

{     

 SCL_L;

 I2C_DELAY;  

 SDA_L;

 I2C_DELAY;  

 SCL_H;

 I2C_DELAY;  

 SCL_L;

 I2C_DELAY;  


/* I2C未响应信号 */

void I2C_NoAck(void)  

{     

 SCL_L;

 I2C_DELAY;  

 SDA_H;

 I2C_DELAY;  

 SCL_H;

 I2C_DELAY;  

 SCL_L;

 I2C_DELAY;  


/* 等待应答信号 */

bool I2C_WaitAck(void)     

{  

 SCL_L;

 I2C_DELAY;  

 SDA_H;

 I2C_DELAY;  

 SCL_H;

 I2C_DELAY;  

 if(SDA_READ)  

 {  

  SCL_L;

  return false;  

 }  

 SCL_L;

 

 return true;  


/* I2C发送一个字节 */

void I2C_SendByte(uint8_t SendByte)   

{  

 uint8_t i = 8;

 

 while(i--)  

 {  

  SCL_L;

  I2C_DELAY;

  if(SendByte & 0x80)

   SDA_H;

  else  

   SDA_L;

  SendByte <<= 1;  

  I2C_DELAY; 

  SCL_H;

  I2C_DELAY;  

 }  

 SCL_L;


/* I2C接收一个字节 */

uint8_t I2C_ReceiveByte(void)    

{   

 uint8_t i = 8;  

 uint8_t ReceiveByte = 0; 


 SDA_H;


 while(i--)  

 {  

  ReceiveByte<<=1;        

  SCL_L;

  I2C_DELAY;  

  SCL_H;

  I2C_DELAY;      

  if(SDA_READ)  

  {  

   ReceiveByte|=0x01;

  }  

 }


 SCL_L;


 return ReceiveByte;  

}


#define CTRL_CODE 0xA0


/* 写一个字节 */

bool EEPROM_Write_Byte(uint8_t block, uint8_t addr, uint8_t *data)

{

 uint8_t cnt = 10;

 

 /* 确认写周期结束,并写入控制字 */

 do

 {

  I2C_Start();

  I2C_SendByte((CTRL_CODE | (block & 0x0E)) & 0xFE);

 }while((I2C_WaitAck() == false) && (--cnt > 0));

 if(cnt == 0)

 {

  I2C_Stop();

  return false; 

 }

 

 /* 写入地址 */

 I2C_SendByte(addr);

 if(I2C_WaitAck() == false)

 {

  I2C_Stop();

  return false;

 }

 

 /* 写入数据 */

 I2C_SendByte(*data);

 if(I2C_WaitAck() == false)

 {

  I2C_Stop();

  return false;

 }


 I2C_Stop();

 

 return true;

}


/* 读一个字节 */

bool EEPROM_Read_Byte(uint8_t block, uint8_t addr, uint8_t *data)

{

 uint8_t cnt = 10;

 

 /* 确认写周期结束,并写入控制字 */

 do

 {

  I2C_Start();

  I2C_SendByte((CTRL_CODE | (block & 0x0E)) & 0xFE);

 }while((I2C_WaitAck() == false) && (--cnt > 0));

 if(cnt == 0)

 {

  I2C_Stop();

  return false; 

 }


 /* 写入地址 */

 I2C_SendByte(addr);

 if(I2C_WaitAck() == false)

 {

  I2C_Stop();

  return false;

 }

 

 /* 写入控制字 */

 I2C_Start();

 I2C_SendByte(CTRL_CODE | (block & 0x0E) | 0x01);

 if(I2C_WaitAck() == false)

 {

  I2C_Stop();

  return false;

 }

 

 /* 读出数据 */

 *data = I2C_ReceiveByte();

 I2C_NoAck();

 

 I2C_Stop();

 

 return true;

}


/* 主函数 */

int main(void)

{

 uint8_t data = 3;


 /* RCC时钟配置 */

 RCC_config();


 /* GPIO配置 */

 GPIO_config();

 

 EEPROM_Write_Byte(0, 0, &data);

 data = 6;

 EEPROM_Read_Byte(0, 0, &data);

 

 while(1)

 {

  delay_ms(1000);

 }

}

上一篇:STM32之BKP原理

下一篇:STM32之I2C原理

推荐阅读

史海拾趣

长园维安(CYGWAYON)公司的发展小趣事

面对电子行业快速发展的挑战,长园维安积极应对,进行转型升级。公司加大研发投入,开发更加智能化、集成化的产品,满足市场需求。同时,长园维安还注重人才培养和引进,建立了一支高素质的技术和管理团队。这些努力使长园维安在激烈的市场竞争中保持领先地位。

Belkin公司的发展小趣事

贝尔金的成功不仅仅局限于美国本土。随着全球市场的不断扩张,贝尔金也在全球范围内建立了广泛的销售网络和物流中心。位于加州洛杉矶的总部、好莱坞的工业设计中心以及纽约州罗切斯特的研发机构,共同构成了贝尔金全球业务的核心。这些机构之间的紧密合作,确保了贝尔金能够迅速响应全球市场的需求,提供高品质的产品和服务。

芯朋微电子(chipown)公司的发展小趣事

随着技术的不断进步和市场需求的增长,芯朋微电子逐步将产品线拓展至标准电源和工业驱动领域。2013年,公司推出工控功率芯片产品,这些芯片广泛应用于电机、基站、智能电表等行业领域,进一步扩大了公司的市场份额。

益升华(Essentra)公司的发展小趣事

为了提高生产效率和降低成本,益升华(Essentra)公司不断优化供应链。公司与多家优质供应商建立了长期稳定的合作关系,确保原材料的质量和供应的稳定性。同时,公司还引入先进的生产设备和工艺,提高生产自动化水平,降低人工成本。此外,益升华(Essentra)公司还建立了完善的物流体系,确保产品能够及时送达客户手中。这些措施的实施,使公司的竞争力得到了显著提升。

EDAL公司的发展小趣事

EDAL公司始终秉持持续创新和客户至上的理念。公司不断投入研发资源,推出新的EDA产品和解决方案,满足客户的多样化需求。同时,EDAL公司还建立了完善的客户服务体系,为客户提供全方位的技术支持和解决方案。这些举措不仅增强了客户对EDAL公司的信任和忠诚度,还为公司的长期发展奠定了坚实的基础。

德芯半导体(Doeshare)公司的发展小趣事

德芯半导体在成立之初就明确了其市场定位:以高性价比的特色传感器系列产品为目标市场。公司秉承“以德治企,创造精品”的经营理念,通过深入了解市场需求,不断推出符合市场需求的创新产品。在智能家居、智能制造等领域,德芯半导体的产品凭借其高性能、高品质和低价格,赢得了国内外知名公司的认证和合作。

问答坊 | AI 解惑

电路板算价工器,值得收藏

电路板算价工器,值得收藏:http://www.sz-jlc.com/home/order_add.jsp      做电路板价比三家,因为电路板的工艺多,询价是一个很麻烦的事,现在不用愁了,只要你收藏这个网址,随时随地都能算价,无论是在哪家下单做板,它可以做一个 ...…

查看全部问答>

关于232串口电平转换芯片,说说我的经历

这几天论坛有两个关于232芯片的讨论帖子 232烧坏咋办 https://bbs.eeworld.com.cn/thread-98986-1-1.html 大家说说sp3223与max3223的区别? https://bbs.eeworld.com.cn/thread-98677-1-1.html 看了仙猫等大侠的分析评论,实在是大开眼界,受 ...…

查看全部问答>

LED灯为什么会取代节能灯

replyreload += \',\' + 379395;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

Keil3 的 debug下编写ini文件 仿真?

最近发现 keil Debug下可以通过编写ini文件仿真,比如我的项目里就有一个I2C通信的ini文件 代码如下: DEFINE int SADR                            ...…

查看全部问答>

CE 5.0 使用剩余NAND作FAT求助

系统中使用64MB的NAND,512Byte 小页模式。前20个block保留给EBOOT。MBR在第21个block。后边的28M格式化成BINFS用来保存NK镜像。把之后的剩余空间格式化成PART_EXT(也试过DOS32)用作存储空间。参考了eeworld上的相关讨论之后,已经可以在文件浏览 ...…

查看全部问答>

Linux下AD驱动,报酬面议!

求助:Linux下AD驱动,用的是ads7842的片子。帮助做个ADS7842的驱动,并采集一些简单的信号。 如果有人熟悉这方面的,请联系:QQ:35590495.报酬面议!在北京!急!!!…

查看全部问答>

错误问题已解决

                                 问题已解决 …

查看全部问答>

【问TI】6713显示断点错误问题

测试程序通过仿真口load成功,但是同时显示断点错误:Can\'t Set Breakpoint at 0x7638: Error 0x00000008/-1076 Error during: Break Point,  Cannot set erify breakpoint at 0x00007638   Sequence ID: 7 Error Code: -1076 ...…

查看全部问答>

微分器误差

本帖最后由 dontium 于 2015-1-23 12:50 编辑 我这边有台 仪器,输出的是速度电压信号,信号有时候有毛刺,噪音,现在想得到加速度;如果直接微分,误差有多大?请教指点 听说有种 非线性跟踪微分器的 性能比较好! 这个怎么实现呢?? 谢谢 ...…

查看全部问答>

富士通FRAM心得提交

Fujitsu的FRAM的性能挺好,我是使用STM32的处理器调试的,经试用后,感觉速度比较快,接口比较简单,比较好用.…

查看全部问答>