一个stm32的I2C比较通俗易懂的入门例程

最新更新时间:2019-04-02来源: eefocus关键字:stm32  I2C  入门例程 手机看文章 扫描二维码
随时随地手机看文章

买了个核心板,算是有自己的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);

}

}

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


关键字:stm32  I2C  入门例程 编辑:什么鱼 引用地址:一个stm32的I2C比较通俗易懂的入门例程

上一篇:STM32F207调试记录之串口配置
下一篇:stm32中i2c之学习浅谈

推荐阅读最新更新时间:2023-08-08 15:05

STM32定时器高效时间片学习
常规单片机运行程序如下: while(1) { ..... } 类似于一种顺序执行的方法,执行起来较为死板,一旦某一行发生错误的时候就会造成整个程序的跑飞,基于以上传统开发所有的缺点。可以设置相关的定时器,进行某种时间片的控制。 首先设置定时器的中断,按照正常的配置相关的时间基点。 例如:将预装载寄存器存放20-1,将预分频寄存器装360-1,计数器没溢出一次形成的是0.5ms的时间,以此为时间基准,使能溢出中断。 之后可以在中断服务函数内设置相关的计数全局变量,每中断一次,对相对应的时间变量+1: 05ms++; 1ms++; ... ... 1000ms++; 在主函数之中根据相关的全局变量,可以每到达以此时间点变执行相
[单片机]
stm32 各头文件或C文件功能
stm32f10x_con.h 配置文件:加载哪个外设、使能assert 对参数进行检查,如果使能了assert 需要在main文件中添加 _assert_faild 函数。 使能assert会增大编译出执行文件的大小,调试完后可以将assert 屏蔽。 stm32f10x.h头文件中包含了stm32f10x_conf.h 。 stm32f10x.h 1、对所有的外设的地址进行映射,映射到存储区,即定义某外设结构体变量,因为结构体是连续存储的只要将外设的基地址强制转换为结构体类型的指针,那么该外设的寄存器就可以通过指针进行访问,以GPIO为例: 定义外设的结构体,结构体变量都
[单片机]
武林教你学PIC32(八)I2C EEPROM 24LC256
首先介绍下EEPROM 24LC256,它是PIC生产的电擦写式只读存储器EEPROM,容量为256KB,支持2线串行接口,也就是I2C接口(不了解I2C自己上网补下功课),它的器件地址为0X1010A2A1A0。其中A2A1A0是可以配置的,板上是连着GND的,所以它的器件地址是0X50。 我们看看板上器件连线形式,可以看到是连接到I2C1上的,而且已经有上拉电阻了。 我们实现的功能就往EEPROM写一个字符,然后再读出,如果相等LED1亮,不相等LED1灭。 OpenI2C1( I2C_EN, BRG_VAL );//初始化 mPORTBClearBits(BIT_10); //LED1=0
[单片机]
武林教你学PIC32(八)<font color='red'>I2C</font> EEPROM 24LC256
STM32在线升级IAP-Hex文件和Bin文件的区别
1 - HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身 在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为HEX文件内部的信息已经包括了地址。而烧写BIN文件的时候,用户是一定需要指定地址信息的。 2- BIN文件格式 对二进制文件而言,其实没有”格式”。文件只是包括了纯粹的二进制数据。
[单片机]
STM32 中嵌套向量中断控制的理解
一、STM32 (Cortex-M3) 中的优先级概念 STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。 1. 何为占先式优先级(pre-emption priority) 高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。 2. 何为副优先级(subpriority) 在占先式优先级相同的情况下,高副优先级的中断优先被响应; 在占先式优先级相同的情况下,如果有低副优先级中断正在执行, 高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到
[单片机]
<font color='red'>STM32</font> 中嵌套向量中断控制的理解
STM32(6) STM32时钟系统精讲(正点原子)
讲解内容: 时钟系统框图 时钟配置相关函数 参考资料 《STM32F4开发指南库函数版本》4.3小节STM32F4时钟系统 《STM32F4中文参考手册》第六章 复位和时钟系统 先看开发指南4.3小节的时钟树 时钟框图在中文参考手册的6.2小节,STM32的时钟系统还是很复杂的,为什么ARM的时钟系统要做的这么复杂,采用 多时钟源, 时钟频率越高功耗 越高。 F4与F1类似也有5个时钟来源 1 LSIRC 低速 的内部时钟 2 LSEOSC 低速的外部时钟 3 HSIRC 高速的内部时钟 4 PLLCLK 锁相环时钟输出 5 HSEOSC 也是一个很重要的时钟源,也是我们最常用的
[单片机]
<font color='red'>STM32</font>(6) <font color='red'>STM32</font>时钟系统精讲(正点原子)
stm32作为spi的从机使用例程
STM32的SPI可以作为master,也可以作为slave,作为slave的例程比较少,今天经过几个小时的折腾,终于把数据获取出来了,经验证和元数据是一致的。现将源代码贴在这里,供有需要的人参考。 硬件连接: STM32(作为从设备) 外部设备 PB12-SPI2-NSS------------ CS PB13-SPI2-SCK------------- CLK PB14-SPI2-MISO----NC PB15_SPI2-MOSI----------- data STM32作为从设备的时候,获取数据的接口为MOSI(PB15),STM32只需要从SPI接口获取数据,不需要发送数据,因此MISO(PB14)悬空。
[单片机]
使用proteus仿真STM32单片机的注意事项
第1点: 我们用户编写的代码,必须放在 user code begin 和 end 之间;否则,当我们修改stm32cubemx 项目的 配置时,再次生成代码,就会删除之前的代码;正确做法如下图所示: 我们用户编写的代码,必须放在 user code begin 和 end 之间 第2点: 在proteus中,电源需要更改成3.3V,VDDA添加到电源VCC/GND中去;VSSA添加到GND中去;如下图所示: 电源需要改成3.3V 第3点: HAL_Delay(__IO uint32_t Delay)延时函数在stm32f1xx_hal.c里面,该函数能实现ms级别的延时;该函数体前面有一个关键字__weak,该关键字简
[单片机]
使用proteus仿真<font color='red'>STM32</font>单片机的注意事项
小广播
设计资源 培训 开发板 精华推荐

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

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

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