STM32F103 KS103超声波IIC实现

一.看图模拟IIC

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)

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_sda_out
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions:  输出模式
**                         
**--------------------------------------------------------------------------------------------------------**/
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);
}

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_sda_in
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions:  输入模式
**                         
**--------------------------------------------------------------------------------------------------------**/
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);
}

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_init
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions:  初始化IO口
**                         
**--------------------------------------------------------------------------------------------------------**/
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由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/a0c4631f8dc94d76b43cd4274bc4ba52.png

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_start
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions:  起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
**                         
**--------------------------------------------------------------------------------------------------------**/
void iic_start(void)
{
	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总线,准备发送或接收数据 
}


/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_stop
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions:  停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
**                         
**--------------------------------------------------------------------------------------------------------**/
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;/*end */
	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是等待应答)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_ack
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: 产生ACK应答 SDA是低电平
**                         
**--------------------------------------------------------------------------------------------------------**/
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;
}
 
/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_nack
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: 不产生ACK应答	SDA是高电平	
**                         
**--------------------------------------------------------------------------------------------------------**/   
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;
}

       
/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_wait_ack
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void  1,接收应答失败 0,接收应答成功      
**@descriptions: 等待应答信号到来
**                         
**--------------------------------------------------------------------------------------------------------**/ 
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的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。在这里插入图片描述

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_send_byte
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: IIC发送书1个字节	
**                         
**--------------------------------------------------------------------------------------------------------**/ 
void iic_send_byte(u8 data)
{                        
    u8 pnext;   
    iic_sda_out(); 	    
    IIC_SCL_L;/*SCL ENABLE*/
    for(pnext=0;pnext<8;pnext++)
    {      
	     /*send direction high_8 to low_8, ready data*/
	     if((data&0x80)>>7){IIC_SDA_H;}
	     else{IIC_SDA_L;}
	     data<<=1; 	
	     delay_us(10); /*SCL is high ,start send data*/  
	     IIC_SCL_H;
	     delay_us(10); 
	     IIC_SCL_L; /*send data end,enable SCL*/	
	     delay_us(10);
    }	 
} 


 
/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  iic_read_byte
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: IIC读取数据1个字节,ack=1时,发送ACK,ack=0,发送nACK 
**                         
**--------------------------------------------------------------------------------------------------------**/  
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;/*SCL is high ,start read data */
         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.读取探测结果和开始探测
在这里插入图片描述
在这里插入图片描述

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  ks103_readonebyte
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: 读取ks103探测结果
**                         
**--------------------------------------------------------------------------------------------------------**/  
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;
}

在这里插入图片描述

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  ks103_writeonebyte
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: 开始ks103探测
**                         
**--------------------------------------------------------------------------------------------------------**/ 
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();
}

/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:   ks103_change_addr
**@author:       
**@data:   
**@param:void :source 当前的ks103地址
**@param:void :destin 新地址
**@return:void        
**@descriptions:  ks103修改地址 default :0xe8
**                         
**--------------------------------------------------------------------------------------------------------**/
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;/*mm*/
 u8 distance_h=0;
 u8 distance_l=0;
/**--------------functiion Info--------------------------------------------------------------------------------- 
**@functiion name:  main
**@author:       
**@data:   
**@param:void
**@param:void
**@return:void        
**@descriptions: 主函数
**                         
**--------------------------------------------------------------------------------------------------------**/ 
void main(void)
{

	  iic_init();
	  
		while(1)
		{
	 		    ks103_writeonebyte(0xE8,0x02,0xb0);/*开始探测 0xe8是超声波地址,0xb0探测指令返回mm*/
	 		    delay_ms(50);
	 		    distance_h = ks103_readonebyte(0xE8, 0x02);/*读取探测结果 0xe8是超声波地址,返回mm*/
	 		    distance_l= ks103_readonebyte(0xE8, 0x03);/*读取探测结果 0xe8是超声波地址,返回mm*/
	 		    result_distance=distance_h<<8 |distance_l;
	 		    delay_ms(50);
		}
}
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值