【菜鸟入门】stm32 之 iic
2020-03-04 来源:eefocus
纠结了两天,终于重新开始写了,这两天一直卡在硬件iic上,由于硬件iic是比较难啃的一块骨头,问题一大堆,明明感觉配置好,测试时,一会出这个问题,一会出那个问题,哎,说多了都是泪。。。。
最后木有办法了,总不能吊死在一棵树上吧,然后就写了个模拟的iic的,由于对iic研究和应用的比较多(我们实验室的设备都是iic通信的,所有设备的驱动都是我来写的),所以在搞这个的时候得心应手,一个小时就把所有的搞定了,有花了1个小时把eeprom(at24c02)调通;
我大致测了下,我的板子上的eeprom电路类似这个:
所以我要做的是就是把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< #define SET_SCL(a) do{ if(a) IIC->ODR |= 1< #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< #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 #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 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 str[i]=iic_recv_byte(); iic_send_ack(0); } str[i] = '