历史上的今天
返回首页

历史上的今天

今天是:2025年04月02日(星期三)

正在发生

2019年04月02日 | 一个stm32的I2C比较通俗易懂的入门例程

2019-04-02 来源:eefocus

买了个核心板,算是有自己的STM32板子了,所以顺便也整一整I2C(因为上面的是24C02,嘻嘻,比较亲切),刚开始的时候,按照参考书上面的例程写了一个读写程序,但是直接把程序下载到板子里串口无数据输出(我是用的串口把读出的数据发送出来),然后我就在FLASH里调试,一步步的走下去,发现程序停在了while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){;},然后就是找各种可能的原因,最后实在不行了就百度了一下,发现了一条重要信息:有些IIC设备读写的时候需要加延时!感觉可能是这个原因,毕竟24C02是I2C的入门级芯片,于是就在程序加了延时函数,下载到板子里,通了!感谢网络上的各位前辈!


下面贴出源代码:


STM32的I2C

I2C.c文件

#include

#include "I2C.h"

#include

#include

void I2C_GPIO_Config()

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void I2C1_Init()

{

I2C_InitTypeDef I2C_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0xA0;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = 400000;

I2C_Cmd(I2C1, ENABLE);

I2C_Init(I2C1, &I2C_InitStructure);

}

void I2C_Write(u8 addr, u8 data)

{

I2C_AcknowledgeConfig(I2C1,ENABLE); //使能应答

I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;}//等待EV5

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter); //发送从地址

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;} //等待EV6

I2C_SendData(I2C1,addr); //发送要写入数据的地址

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8

I2C_SendData(I2C1,data); //发送要写入的数据

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8

I2C_GenerateSTOP(I2C1,ENABLE); //发送停止位

}

u8 I2C_Read(u8 nAddr)

{

I2C_AcknowledgeConfig(I2C1,ENABLE); //使能应答

I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;} //等待EV5

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter); //发送一个伪写指令

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;}//等待EV6

I2C_SendData(I2C1,nAddr);//发送读地址

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8

I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;} //等待EV5

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver); //发送一个读指令

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){;} //等待EV6

I2C_AcknowledgeConfig(I2C1,DISABLE); //应答使能关闭

I2C_GenerateSTOP(I2C1,ENABLE); //发送一个停止位

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){;} //等待EV7

return I2C_ReceiveData(I2C1); //返回读到的数据

}

Usart.c文件

#include

#include"usart.h"

void usart_gpio_config()

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA,&GPIO_InitStructure);

}

void usart_init()

{

USART_InitTypeDef USART_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

USART_InitStructure.USART_BaudRate = 9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1,&USART_InitStructure);

USART_Cmd(USART1,ENABLE);

}

void usart_putchar(u8 ch)

{

USART_SendData(USART1,ch);

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);

}

delay.c文件

#include

#include "delay.h"

static u8 fac_us=0;//us延时倍乘数

static u16 fac_ms=0;//ms延时倍乘数

//初始化延迟函数

//SYSTICK的时钟固定为HCLK时钟的1/8

//SYSCLK:系统时钟

void delay_init(u8 SYSCLK)

{

SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟 HCLK/8

fac_us=SYSCLK/8;

fac_ms=(u16)fac_us*1000;

}

//延时nms

//注意nms的范围

//SysTick->LOAD为24位寄存器,所以,最大延时为:

//nms<=0xffffff*8*1000/SYSCLK

//SYSCLK单位为Hz,nms单位为ms

//对72M条件下,nms<=1864

void delay_ms(u16 nms)

{

u32 temp;

SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)

SysTick->VAL =0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do

{

temp=SysTick->CTRL;

}

while(temp&0x01&&!(temp&(1<<16)));//等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

//延时nus

//nus为要延时的us数.

void delay_us(u32 nus)

{

u32 temp;

SysTick->LOAD=nus*fac_us; //时间加载

SysTick->VAL=0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do

{

temp=SysTick->CTRL;

}

while(temp&0x01&&!(temp&(1<<16)));//等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

main.c文件

#include

#include "I2C.h"

#include "Usart.h"

#include "delay.h"

int main()

{

SystemInit();

delay_init(72);

I2C_GPIO_Config();

I2C1_Init();

usart_gpio_config();

usart_init();

I2C_Write(0x10,0x30);

delay_ms(10);

while(1)

{

usart_putchar(I2C_Read(0x10));

delay_ms(1000);

}

}

因为只是想试验一下,所以就只是写入一个数据,然后通过串口读出写入的数据,仅此而已。


推荐阅读

史海拾趣

HN Electronic Components GmbH & Co Kg公司的发展小趣事

背景:近年来,随着全球对环境保护和可持续发展的重视,电子行业也面临着绿色转型的压力。

发展:HN Electronics积极响应环保号召,将绿色生产理念融入公司的发展战略中。公司投入大量资金进行技术改造和设备升级,减少生产过程中的能耗和污染排放。同时,HN Electronics还积极研发和推广绿色电子产品,满足市场对环保产品的需求。

关键事件:2020年,HN Electronics推出了一系列采用环保材料和先进生产工艺的绿色电子产品,这些产品不仅性能优异,而且符合国际环保标准,赢得了市场的广泛好评。

DART(英国达特)公司的发展小趣事

在快速发展的过程中,DART公司也遇到了不少挑战和危机。例如,某个时期全球电子元器件供应紧张,导致公司面临严重的原材料短缺问题。面对这一挑战,DART公司迅速调整采购策略,积极寻找新的供应商和替代品,并加强与现有供应商的合作和沟通。通过这些措施,公司成功度过了危机,并保持了业务的稳定增长。

Chyao Shiunn Electronic Industrial Ltd公司的发展小趣事

在电子行业的初期,Chyao Shiunn Electronic Industrial Ltd还是一家名不见经传的小公司。然而,凭借着对技术创新的执着追求,公司成功研发出一款高效能的芯片,这款芯片不仅性能卓越,而且成本相对较低。这一技术突破迅速吸引了市场的关注,公司借此机会积极拓展市场,逐渐在电子行业中崭露头角。

Fascomp公司的发展小趣事

在快速发展的过程中,Fascomp始终注重企业文化建设和人才培养。公司倡导“创新、协作、务实、进取”的价值观,鼓励员工积极创新、勇于挑战。同时,公司还注重人才培养和引进,建立了一套完善的人才培养和激励机制。这些举措为公司的发展提供了坚实的人才保障。

CAO Group Inc公司的发展小趣事

CAO Group, Inc.的创始人Densen Cao博士,以其对电子行业的深厚理解和对创新的执着追求,于2000年创立了这家公司。他带领团队,凭借第一台LED固化灯的发明,成功打破了当时市场的技术壁垒,为公司的初期发展奠定了坚实的基础。这款LED固化灯凭借其高效、稳定、环保的特性,迅速获得了市场的认可,为公司的后续发展注入了强大的动力。

ELPIDA公司的发展小趣事

ELPIDA公司成立于1999年,是日本在DRAM(动态随机存取存储器)领域的重要企业。它的成立是对当时日本半导体产业的一次重要整合,由NEC、日立、三菱电机等公司的DRAM业务合并而成。这一举措旨在振兴日本在DRAM领域的竞争力,并保护国内DRAM产业。

问答坊 | AI 解惑

鼎芯推出我国首款PHS/PAS(小灵通)手机射频芯片单片机

芯片设计企业鼎芯半导体公司(Comlent)近日宣布开发出我国首款用于PHS/PAS(俗称“小灵通”)手机的完整射频集成电路(RFIC)收发器和功率放大器(PA)芯片组。         据介绍,这两款编号分别为CL3110 和CL3503的收发器和功 ...…

查看全部问答>

MI200E 电力线载波通讯芯片

简述: MI200E 是一款专门针对低压电力线进行优化设计的高集成度、高性能的电力线载波通讯芯片。 MI200E 是一个可工作于码分多址(CDMA)方式的半双工调制解调芯片。并且提供载波侦听和有效帧指示信号,可方便地实现基于共享信道的网络接入协议。…

查看全部问答>

跪求电路图

小弟正在作isa卡  就是把双口ram(8k*8)通过isa总线映射到内存中的那种 想要一分电路参考一下 我的邮箱     nankaigg@163.com   先谢谢了…

查看全部问答>

硬件,驱动的迷茫

大家好,我目前从事硬件设计工作,一个人负责一个项目,平时就画画原理图,调试一下板子,主要的工作还是发现问题,解决问题的过程。感觉如果纯粹搞硬件的话好像没什么东西好搞,电路都是现成的。 学了两个月左右的WINCE驱动,在自己所负责的板子 ...…

查看全部问答>

跪求WINCE5 的DM320 BSP文件,另有2个问题请教,分不够可以在加在线等待

哪位好心人能给我个DM320的BSP文件。另外在问2个问题: 1.我的PLATFORM是英文版,编译出来的都是英文的,如何编译出中文的ROM 2.我可以成功编译出nk.bin,但是怎么得到nk.cem,就是可以在模拟器运行哪(我编译的就是X86的EMU的)? …

查看全部问答>

SQLCE+CE4.2+EVC4.0创建数据库连接时代码CoCreateInstance()出错

我用的是SQLCE2.0+CE4.2+EVC4.0,PDA(PPC2003)端可建立数据库。 在调试程序时,以下代码总是出错,即pCERDA 指针不能创建,该问题在PPC2003和wince4.2下同样出现。 ISSCERDA* pCERDA = NULL; //得到pCERDA接口 HRESULT hr = CoCreateInstance ...…

查看全部问答>

闲来无事,讨论个大家都容易忽略的问题

如下:     struct sta     {         char a;         int   b;     };     struct stb     {   ...…

查看全部问答>

msp-fet430UIF郁闷

我的笔记本只有4个usb口,以前只能用usb转rs232用编程器开发程序,现在看到了由usb接口的jtag fet十分激动,买了一个,可是软件又不支持 v3.20真让我郁闷,现在有的回去用我的msp430prgs-III了。 真是不胜感激!!…

查看全部问答>

关于430的倍频问题

首先 请问是不是430只有4和5系列才能倍频 另外 做一个项目 需要cpu频率到70mHz fe425可以倍频到70 但是能正常工作吗?求助…

查看全部问答>

高薪诚聘:手机硬件工程师

深圳市邦旭科技有限公司从事于消费类电子产品的软硬件开发。公司的核心理念是诚信、创新、敬业、分享。公司主张创新、主张技术人员劳动的价值。公司的理想是通过点点滴滴的努力和积累,赢得尊重和可持续发展。        当前, ...…

查看全部问答>