1.宏定义io和初始化io
#define IIC_SCL_PORT GPIOC
#define IIC_SCL_PIN GPIO_Pin_3
#define IIC_SCL_L GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN)
#define IIC_SCL_H GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN)
#define IIC_SDA_PORT GPIOC
#define IIC_SDA_PIN GPIO_Pin_2
#define IIC_READ_SDA GPIO_ReadInputDataBit(IIC_SDA_PORT,IIC_SDA_PIN)
#define IIC_SDA_L GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN)
#define IIC_SDA_H GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN)
void iic_sda_out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
void iic_sda_in(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
void iic_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD
| RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
IIC_SCL_H;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
IIC_SDA_H;
}
2.模拟:启动信号 停止信号
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

{
iic_sda_out();//sda线输出
IIC_SDA_H;
IIC_SCL_H;
delay_us(10);
IIC_SDA_L;//start:when CLK is high,DATA change form high to low
delay_us(10);
IIC_SCL_L;//钳住I2C总线,准备发送或接收数据
}
void iic_stop(void)
{
iic_sda_out();//sda线输出
IIC_SCL_L;
IIC_SDA_L;//stop:when SCL is high,DATA change form low to high
delay_us(10);
IIC_SCL_H;
delay_us(2);
IIC_SDA_H;
delay_us(10);
}
3.模拟:应答信号 、非应答信号、等待应答信号
发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。(大白话理解应答:A向B读取数据,A是接收数据者,B是发送数据者。A接收完一个8位数据后,要发送一个信号告诉B让它结束发送。该信号分高电平和低电平,A是发送应答,B是等待应答)
void iic_ack(void)
{
IIC_SCL_L;
iic_sda_out();
IIC_SDA_L;
delay_us(10);
IIC_SCL_H;
delay_us(10);
IIC_SCL_L;
}
void iic_nack(void)
{
IIC_SCL_L;
iic_sda_out();
IIC_SDA_H;
delay_us(10);
IIC_SCL_H;
delay_us(10);
IIC_SCL_L;
}
u8 iic_wait_ack(void)
{
u8 wait_time=0;
IIC_SDA_H;
delay_us(6);
IIC_SCL_H;
delay_us(6);
iic_sda_in(); //SDA设置为输入
while(IIC_READ_SDA)
{
wait_time++;
if(wait_time>250)
{
iic_stop();
return 1;
}
}
IIC_SCL_L;
return 0;
}
4.模拟:发送数据、接收数据
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
void iic_send_byte(u8 data)
{
u8 pnext;
iic_sda_out();
IIC_SCL_L;
for(pnext=0;pnext<8;pnext++)
{
if((data&0x80)>>7){IIC_SDA_H;}
else{IIC_SDA_L;}
data<<=1;
delay_us(10);
IIC_SCL_H;
delay_us(10);
IIC_SCL_L;
delay_us(10);
}
}
u8 iic_read_byte(u8 ack)
{
u8 pnext,receive=0;
iic_sda_in();//SDA设置为输入
for(pnext=0;pnext<8;pnext++ )
{
IIC_SCL_L;
delay_us(10);
IIC_SCL_H;
receive<<=1;
if(IIC_READ_SDA)receive++;
delay_us(5);
}
if (!ack)
iic_nack();//发送nACK
else
iic_ack(); //发送ACK
return receive;
}
二KS103探测距离
1.官网手册地址如下:http://www.dauxi.com/KS10X-V110_CN.pdf
2.读取探测结果和开始探测
u8 ks103_readonebyte(u8 addr, u8 reg)
{
u8 result=0;
iic_start();
iic_send_byte(addr);
iic_wait_ack();
iic_send_byte(reg);
iic_wait_ack();
iic_start();
iic_send_byte(addr+ 1);
iic_wait_ack();
delay_us(50);
result=iic_read_byte(0);
iic_stop();
return result;
}
void ks103_writeonebyte(u8 addr,u8 reg,u8 cmd)
{
iic_start();
iic_send_byte(addr);
iic_wait_ack();
iic_send_byte(reg);
iic_wait_ack();
iic_send_byte(cmd);
iic_wait_ack();
iic_stop();
}
void ks103_change_addr(u8 source, u8 destin)
{
ks103_writeonebyte(source,0x02,0x9a);
delay_ms(5);
ks103_writeonebyte(source,0x02,0x92);
delay_ms(5);
ks103_writeonebyte(source,0x02,0x9e);
delay_ms(5);
ks103_writeonebyte(source,0x02,destin);
delay_ms(500);
}
u16 result_distance=0;
u8 distance_h=0;
u8 distance_l=0;
void main(void)
{
iic_init();
while(1)
{
ks103_writeonebyte(0xE8,0x02,0xb0);
delay_ms(50);
distance_h = ks103_readonebyte(0xE8, 0x02);
distance_l= ks103_readonebyte(0xE8, 0x03);
result_distance=distance_h<<8 |distance_l;
delay_ms(50);
}
}



