【菜鸟入门】stm32 之 iic

最后更新于:2022-04-01 14:50:42

纠结了两天,终于重新开始写了,这两天一直卡在硬件iic上,由于硬件iic是比较难啃的一块骨头,问题一大堆,明明感觉配置好,测试时,一会出这个问题,一会出那个问题,哎,说多了都是泪。。。。 最后木有办法了,总不能吊死在一棵树上吧,然后就写了个模拟的iic的,由于对iic研究和应用的比较多(我们实验室的设备都是iic通信的,所有设备的驱动都是我来写的),所以在搞这个的时候得心应手,一个小时就把所有的搞定了,有花了1个小时把eeprom(at24c02)调通; 我大致测了下,我的板子上的eeprom电路类似这个: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915b3636f0.jpg) 所以我要做的是就是把PB6配置称时钟线SCL,PB7配置成数据线SDA 这里我们再配置输出的时候,要把管脚配置成 General purpose output push-pull模式,具体原因看datasheet关于管脚配置的那章口头,说的很清楚; 先给大家看看我的头文件里面的定义 ~~~ #ifndef __IIC_H__ #define __IIC_H__ #define INPUT 0x8 #define OUTPUT 0x3 /* Config GPIOx */ #define IIC GPIOB #define SCL_BIT 6 #define SDA_BIT 7 /*Set & Get GPIOx Value*/ #define SET_SDA(a) do{\ if(a) IIC->ODR |= 1<<SDA_BIT;\ else IIC->ODR &= ~(1<<SDA_BIT);\ }while(0) #define SET_SCL(a) do{\ if(a) IIC->ODR |= 1<<SCL_BIT;\ else IIC->ODR &= ~(1<<SCL_BIT);\ }while(0) #define SDA_OUT do{ \ IIC->CRL &= ~((unsigned int)0xf<<(4*SDA_BIT));\ IIC->CRL |= (unsigned int)OUTPUT<<(4*SDA_BIT);\ }while(0) #define SDA_IN do{\ IIC->CRL &= ~((unsigned int)0xf<<(4*SDA_BIT));\ IIC->CRL |= (unsigned int)INPUT<<(4*SDA_BIT);\ }while(0) #define SDA_VAL (IIC->IDR&(1<<SDA_BIT)) #define SDA_H SET_SDA(1) #define SDA_L SET_SDA(0) #define SCL_H SET_SCL(1) #define SCL_L SET_SCL(0) #define DELAY delay_us(10) #define SLAVE_ADDR 0xA0 #define IIC_READ 0x01 #define IIC_WRITE 0x00 extern int iic_init(void); extern void iic_start(void); extern void iic_stop(void); extern void iic_send_ack(unsigned char ack); extern unsigned char iic_recv_ack(void); extern void iic_send(unsigned char bit); extern unsigned char iic_send_byte(unsigned char dat); extern unsigned char iic_recv(void); extern unsigned char iic_recv_byte(void); extern int iic_send_str(char str[],int len); extern void iic_recv_str(char str[],int len); #endif ~~~ 下面是iic的应用函数 ~~~ #include <stm32f10x.h> #include "init.h" #include "iic.h" /* SCL PB6 SDA PB7 */ int iic_init() { RCC->APB2ENR |= 1<<3; //Set Clock for GPIOB IIC->CRL &= ~((unsigned int)0xf<<(4*SCL_BIT)); IIC->CRL |= (unsigned int)OUTPUT<<(4*SCL_BIT); //config scl IIC->CRL &= ~((unsigned int)0xf<<(4*SDA_BIT)); IIC->CRL |= (unsigned int)OUTPUT<<(4*SDA_BIT); //config sda return 1; } void delay5us() { DELAY; } /* iic start */ void iic_start() { SDA_OUT; SCL_H; SDA_H;DELAY; SDA_L;DELAY; SCL_L; } /* iic stop */ void iic_stop() { SDA_OUT; SCL_L;SDA_L; SCL_H;DELAY; SDA_H;DELAY; } /* * iic send ack * ack (0:ACK 1:NAK) */ void iic_send_ack(unsigned char ack) { SDA_OUT;SCL_L; if(ack == 0x00) SDA_L; if(ack == 0x01) SDA_H; DELAY; SCL_H;DELAY; SCL_L;DELAY; } /* receive ack */ unsigned char iic_recv_ack() { u32 val = 0; SDA_IN; SCL_H;DELAY; val = SDA_VAL; SCL_L;DELAY; return (val!=0 ? 1:0); } /* send one bit*/ void iic_send(unsigned char bit) { SCL_L; if(bit == 0x01) SDA_H; else SDA_L; DELAY; SCL_H;DELAY; SCL_L;DELAY; } /* send one byte */ unsigned char iic_send_byte(unsigned char dat) { unsigned char i = 0; SDA_OUT; for(i=0; i<8; i++) { if(dat & 0x80) iic_send(0x01); else iic_send(0x00); dat <<= 1; } return 1; } /* iic receive bit */ unsigned char iic_recv() { u32 bit = 0; SCL_L; SCL_H;DELAY; bit = SDA_VAL; SCL_L;DELAY; return (bit!=0 ? 1:0); } /* iic receive byte */ unsigned char iic_recv_byte() { unsigned char i; unsigned char dat = 0; SDA_IN; for (i=0; i<8; i++) { dat <<= 1; dat |= iic_recv(); } return dat; } int iic_send_str(char str[],int len) { int i=0; for(i=0; i<len; i++) { iic_send_byte(str[i]); if(iic_recv_ack()) return i; } return len; } void iic_recv_str(char str[],int len) { int i=0; for(i=0; i<len; i++) { str[i]=iic_recv_byte(); iic_send_ack(0); } str[i] = '\0'; } ~~~ 就这多,关于iic协议的解析请看我的百度博客:[http://hi.baidu.com/home/](http://hi.baidu.com/home/)ie_code 非常好的分析:[http://blog.gkong.com/zjcsharp_113287.ashx](http://blog.gkong.com/zjcsharp_113287.ashx) [http://www.openedv.com/posts/list/18461.htm](http://www.openedv.com/posts/list/18461.htm) 蓝桥杯-嵌入式交流群 147520657
';