【菜鸟入门】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