stm32f4标准库开发——模拟iic 主要概念: IIC总线:I2C 总线是一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。 IIC总线定义:时钟线:sck 数据线:sda 软件模拟:通过软件控制普通 GPIO 引脚高低点评切换,来模拟总线时序,从而达到与总线协议一样的效果。 缺点:与使用硬件 IIC 相比,会占用更多的 CPU 时间。 实验目的: 本实现通过软件模拟 IIC 时序,编写 IIC 发送接收函数。 硬件电路: 本实验的蜂鸣器为有源蜂鸣器 IIC_SCL IIC_SDA 主要库函数调用: MODER&=~(3< MODER|=0<<9*2;} MODER&=~(3< MODER|=1<<9*2;} #define iic_sda_out(x) PBout(9)=x #define iic_scl_out(x) PBout(8)=x #define iix_read_sda() PBin(9) 代码: //iic.c #include "iic.h" #include "base.h" #include "delay.h" //*********************************************************************** //移植修改部分 MODER&=~(3< MODER|=0<<9*2;} MODER&=~(3< MODER|=1<<9*2;} #define iic_sda_out(x) PBout(9)=x #define iic_scl_out(x) PBout(8)=x #define iix_read_sda() PBin(9) static void iic_gpio_init( void ) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); } static void iic_gpio_deinit( void ) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); } //*********************************************************************** void iic_init( void ) { iic_gpio_init(); iic_scl_out( 1 ); iic_sda_out( 1 ); } void iic_deinit( void ) { iic_gpio_deinit(); iic_scl_out( 1 ); iic_sda_out( 1 ); } void iic_start( void ) { sda_out(); iic_sda_out( 1 ); iic_scl_out( 1 ); delay_us( 4 ); iic_sda_out( 0 ); delay_us( 4 ); iic_scl_out( 0 ); } void iic_stop( void ) { sda_out(); iic_scl_out( 0 ); iic_sda_out( 0 ); delay_us( 4 ); iic_scl_out( 1 ); iic_sda_out( 1 ); delay_us( 4 ); } uint8_t iic_wait_ack( void ) { uint8_t ucerrtime = 0 ; sda_in(); iic_sda_out( 1 ); delay_us( 1 ); iic_scl_out( 1 ); delay_us( 1 ); while (iix_read_sda()) { ucerrtime++; if 250 ) { iic_stop(); return 1 ; } } iic_scl_out( 0 ); return 0 ; } void iic_ack( void ) { iic_scl_out( 0 ); sda_out(); iic_sda_out( 0 ); delay_us( 2 ); iic_scl_out( 1 ); delay_us( 2 ); iic_scl_out( 0 ); } void iic_nack( void ) { iic_scl_out( 0 ); sda_out(); iic_sda_out( 1 ); delay_us( 2 ); iic_scl_out( 1 ); delay_us( 2 ); iic_scl_out( 0 ); } void iic_send_byte( uint8_t txd) { uint8_t t; sda_out(); iic_scl_out( 0 ); for (t = 0 ; t < 8 ; t++) { iic_sda_out((txd & 0x80 7 ); txd <<= 1 ; delay_us( 2 ); iic_scl_out( 1 ); delay_us( 2 ); iic_scl_out( 0 ); delay_us( 2 ); } } uint8_t iic_read_byte( unsigned char ack) { unsigned char i, receive = 0 ; sda_in(); for (i = 0 ; i < 8 ; i++ ) { iic_scl_out( 0 ); delay_us( 2 ); iic_scl_out( 1 ); receive <<= 1 ; if (iix_read_sda()) receive++; delay_us( 1 ); } if (!ack) iic_nack(); else iic_ack(); return receive; } //iic.h #ifndef _IIC_H #define _IIC_H #include "stdint.h" void iic_init( void ); void iic_deinit( void ); void iic_start( void ); void iic_stop( void ); void iic_send_byte( uint8_t txd); uint8_t iic_read_byte( unsigned char ack); uint8_t iic_wait_ack( void ); void iic_ack( void ); void iic_nack( void ); void iic_write_one_byte( uint8_t daddr, uint8_t addr, uint8_t data); uint8_t iic_read_one_byte( uint8_t daddr, uint8_t addr); #endif 编译运行:result 如下,编译无报错,无警告。 总结: 理论上gpio操作加上精确的延时,能模拟出任何总线的时序 iic.c将移植部分单独摘取出来,方便未来的移植开发 公众号: 关注公众号 InsertingAll,获取嵌入式学习资源,学习更多嵌入式知识 搜索 复制