程序代码及注释如下:
#include "IIC.h"
  • #include "Delay.h"
  • //初始化IIC
  • void IIC_Init(void)
  • {
  • GPIO_InitTypeDef GPIO_InitStructure;
  • //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
  • RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //推挽输出
  • GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  • GPIO_Init(GPIOB, &GPIO_InitStructure);
  • IIC_SCL=1;
  • IIC_SDA=1;
  • }
  • //产生IIC起始信号
  • void IIC_Start(void)
  • {
  • SDA_OUT(); //sda线输出
  • IIC_SDA=1;
  • IIC_SCL=1;
  • Delay_us(4);
  • IIC_SDA=0;//START:when CLK is high,DATA change form high to low
  • Delay_us(4);
  • IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
  • }
  • //产生IIC停止信号
  • void IIC_Stop(void)
  • {
  • SDA_OUT();//sda线输出
  • IIC_SCL=0;
  • IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
  • Delay_us(4);
  • IIC_SCL=1;
  • Delay_us(4); //hu add
  • IIC_SDA=1;//发送I2C总线结束信号
  • //Delay_us(4);// hu cut
  • }
  • //等待应答信号到来
  • //返回值:1,接收应答失败
  • // 0,接收应答成功
  • u8 IIC_Wait_Ack(void)
  • {
  • u8 ucErrTime=0;
  • //IIC_SDA=0;Delay_us(1);//hu add
  • SDA_IN(); //SDA设置为输入
  • //IIC_SDA=1;Delay_us(1);//hu cut
  • IIC_SCL=1;Delay_us(1);
  • while(READ_SDA)
  • {
  • ucErrTime++;
  • if(ucErrTime>250)
  • {
  • IIC_Stop();
  • return 1;
  • }
  • }
  • IIC_SCL=0;//时钟输出0
  • return 0;
  • }
  • //产生ACK应答
  • void IIC_Ack(void)
  • {
  • IIC_SCL=0;
  • SDA_OUT();
  • IIC_SDA=0;
  • Delay_us(2);
  • IIC_SCL=1;
  • Delay_us(2);
  • IIC_SCL=0;
  • }
  • //不产生ACK应答
  • void IIC_NAck(void)
  • {
  • IIC_SCL=0;
  • SDA_OUT();
  • IIC_SDA=1;
  • Delay_us(2);
  • IIC_SCL=1;
  • Delay_us(2);
  • IIC_SCL=0;
  • }
  • //IIC发送一个字节
  • //返回从机有无应答
  • //1,有应答
  • //0,无应答
  • void IIC_Send_Byte(u8 txd)
  • {
  • u8 t;
  • SDA_OUT();
  • IIC_SCL=0;//拉低时钟开始数据传输
  • for(t=0;t<8;t++)
  • {
  • IIC_SDA=(txd&0x80)>>7;
  • txd<<=1;
  • Delay_us(2); //对TEA5767这三个延时都是必须的
  • IIC_SCL=1;
  • Delay_us(2);
  • IIC_SCL=0;
  • Delay_us(2);
  • }
  • }
  • //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  • u8 IIC_Read_Byte(void)
  • {
  • u8 i,receive=0x00;
  • SDA_IN();//SDA设置为输入
  • for(i=0;i<8;i++ )
  • {
  • IIC_SCL=0;
  • Delay_us(2);
  • IIC_SCL=1;
  • receive<<=1;
  • if(READ_SDA)
  • receive|= 0x01;
  • Delay_us(1);
  • }
  • return receive;
  • }
  • //IIC 往指定地址Address里写Data
  • void IIC_Write_Addr_Data(u8 address,u8 data)
  • {
  • u8 w_addr,w_data;
  • w_addr = address;
  • w_data = data;
  • IIC_Start();
  • IIC_Send_Byte(0x00);
  • IIC_Wait_Ack();
  • IIC_Send_Byte(w_addr);
  • IIC_Ack();
  • IIC_Send_Byte(w_data);
  • IIC_Ack();
  • IIC_Stop();
  • Delay_us(4);
  • }
  • //IIC 读指定地址Address里写Data
  • u8 IIC_Read_Addr_Data(u8 address)
  • {
  • u8 r_addr,data=0x00;
  • r_addr = address;;
  • IIC_Start();
  • IIC_Send_Byte(0x00);
  • IIC_Wait_Ack();
  • IIC_Send_Byte(r_addr);
  • IIC_Ack();
  • IIC_Start();
  • IIC_Send_Byte(0x01);
  • IIC_Wait_Ack();
  • data = IIC_Read_Byte();
  • IIC_NAck();
  • IIC_Stop();
  • Delay_us(4);
  • return data;
  • }
  • 复制代码