#include "delay.h"
#include "iic.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_rcc.h"
#include "stdio.h"
void iic_init(void) //icc初始化
{
//PB8-sCL PB9-sDa
//开启PB的使能时钟
RCC->AHBENR |=0x01<<18;
//配置模式-输出
GPIOB->MODER &=~((0x03<<(2*8))|(0x03<<(2*9)|(0x01<<24)));
GPIOB->MODER |=(0x01<<(2*8))|((0x01)<<(2*9));
//配置输出类型-开漏
GPIOB->OTYPER &=~((0x03<<8)|(0x03<<9));
GPIOB->OTYPER |=(0x01<<8)|(0x01<<9);
//配置输出速率-2M
GPIOB->OSPEEDR &=~((0x03<<(2*8))|(0x03<<(2*9)));
//配置上下拉-X浮空,,上拉
// GPIOB->PUPDR |=(0x01<<(2*8))|(0x01<<(2*9));
GPIOB->PUPDR &=~((0x01<<(2*8))|(0x01<<(2*9)));
GPIOB->ODR |=0x01<<8;
GPIOB->ODR |=0x01<<9;
}
//产生iic起始信号
void iic_start(void)
{
GPIOB->ODR |=0x01<<9;
delay_us(1);
GPIOB->ODR |=0x01<<8;
delay_us(3);
GPIOB->ODR &=~(0x01<<9);//sTaRT:when CLK is high,DaTa change form high to low
delay_us(4);
GPIOB->ODR &=~(0x01<<8);//钳住I2C总线,准备发送或接收数据
}
//产生iic停止信号
void iic_stop(void)
{
GPIOB->ODR &=~(0x01<<8);
GPIOB->ODR &=~(0x01<<9);//sTOP:when CLK is high DaTa change form low to high
delay_us(4);
GPIOB->ODR |=0x01<<8;//发送I2C总线结束信号
delay_us(1);
GPIOB->ODR |=0x01<<9;//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 iic_read_ack(void)
{
u8 ucErrTime=0;
GPIOA->ODR |=0x01<<9;
delay_us (2);
GPIOB->ODR |=0x01<<8; //sDa设置为输入
delay_us (2);
while(GPIOB ->IDR &GPIO_Pin_9)
{
ucErrTime++;
printf(" %d ",ucErrTime);
if(ucErrTime>250)
{
iic_stop();
return 1;
}
}
GPIOB->ODR |=0x01<<8;
return 0;
}
//不产生aCK应答
void iic_nack(void)
{
GPIOB->ODR &=~(0x01<<8);
GPIOB->ODR |=0x01<<9;
delay_us(2);
GPIOB->ODR |=0x01<<8;
delay_us(2);
GPIOB->ODR &=~(0x01<<8);
}
//iic发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void iic_write_byte(u8 data)
{
u8 i;
for(i=0;i<8;i++)
{
if(data & 0x80) //取出data最高位,如果为1
{
//printf(" %d ",data & 0x80);
GPIOB->ODR |=0x01<<9;
}
else //取出data最高位,如果为0
{
GPIOB->ODR &=~(0x01<<9);
// printf(" %d ",data & 0x80);
}
data=data<<1;
delay_us(2);
GPIOB->ODR |=0x01<<8;
delay_us(2);
GPIOB->ODR &=~(0x01<<8);
delay_us(2);
}
GPIOB->ODR |=0x01<<8; //方便下一步操作
}
//读1个字节,ack=1时,发送aCK,ack=0,发送naCK
u8 iic_read_byte(u8 ack)
{
unsigned char i,data=0;
//sDa设置为输入
GPIOB->ODR &=~(0x01<<9);
GPIOB ->MODER &=~(0x03<<18);
delay_us(1);
GPIOB->ODR &=~(0x01<<8);
for(i=0;i<8;i++)
{
GPIOB->ODR &=~(0x01<<8);
delay_us(2);
GPIOB->ODR |=0x01<<8;
data<<=1;
//printf("%d",GPIOB->IDR &0X01<<9);
if(GPIOB->IDR &0X01<<9)
data++;
delay_us(1);
}
GPIOB->ODR &=~(0x01<<8);
if (!ack)
iic_nack();//发送naCK
else
iic_write_ack(); //发送aCK
GPIOB ->MODER |=0x01<<18;
return data;
}
void iic_write_ack(void)
{
GPIOB->ODR &=~(0x01<<8);
GPIOB->ODR &=~(0x01<<9);
delay_us(2);
GPIOB->ODR |=0x01<<8;
delay_us(2);
GPIOB->ODR &=~(0x01<<9);
}