一、前言
此片文章主要介绍如果通过51系列开发板来读取TOF250(IIC接口)数据的教程
由于51芯片一般不太有IIC接口,此篇主要介绍通过模拟IIC来读取的案例。
提示:以下的案例仅供参考学习使用
二、硬件准备
-
TOF250 :测距传感器
-
51系列开发板:STC12C5A60S2 主频12M
提示:51系列开发板种类较多,此处不专门举例
详细资料可以参考:STC 官网
-
电脑 :Windows 7/10/11
-
TTL转USB:本次测试使用CH340芯片转接板
-
杜邦线:各类(若干)
-
TOF250尾线:购买时自带有一根尾线
二、软件准备
- KEIL IDE:参考官网下载安装教程
三、硬件接线图
提示:实际在测试过程中不建议接上图黄色的线
说明:
- STC12C5A60S2共有两个串口,不过此次测试仅使用一个串口,方便理解
- 此时使用的是模拟IIC接口来读取TOF250的数据
- USB打印结果需要用到串口1的TX
四、例程源码
mian.c
/**************************************************************
**技术论坛:https://blog.csdn.net/HCJ_Application/article/details/124058266
**修改日期:2022/4/24
**技术说明:基于STC12C5A60S2单片机,主频12M
**版本:V1.0
**作者:深圳市弘成基科技有限公司
**************************************************************/
#include <STC12C5A60S2.h>
#include <stdio.h>
#include "myiic.h"
#define TOF250_DIST_H 0x00 //TOF250距离值高8位
#define TOF250_DIST_L 0x01 //TOF250距离值低8位
#define TOF250_READ_L 2 //TOF250读取的长度
#define TOF250_ID 0x52 //TOF250的IIC地址
unsigned char data RxData[10]; //IIC接口接收数据区
unsigned int Tof250_dist = 0; //读取到TOF250的具体数值
void Uart1_SendChar(unsigned char Udat) ;
void UartInit(void) //9600bps@12.000MHz
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xB2; //设置定时初始值
TH1 = 0xB2; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
ES = 1; //打开串口接收中断
EA = 1; //打开所有中断
}
char putchar(char c)
{
Uart1_SendChar(c);
return c;
}
void Uart1_SendChar(unsigned char Udat)
{
SBUF=Udat; //将要发送的数据放入串口数据缓冲区
while(!TI); //等待发送完成
TI=0; //清零TI发送完成标记
}
//定义一个延时
void Delay100ms() //@12.000MHz
{
unsigned char i, j, k;
i = 5;
j = 144;
k = 71;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
UartInit(); //串口初始化,使用9600波特率打印IIC读到的距离值
while(1) {
tof250_i2c_read(TOF250_ID,TOF250_DIST_H, &RxData[0], TOF250_READ_L); //通过IIC读取TOF250距离值信息
Tof250_dist = RxData[1] + RxData[0]*256; //转换成距离值
printf("%u cm\n",Tof250_dist); //串口1直接打印输出
Delay100ms(); //延时100ms,TOF250默认更新速度10HZ
}
}
myiic.h
#ifndef _MYIIC_H_
#define _MYIIC_H_
#include <STC12C5A60S2.h>
sbit SCL = P2^3;
sbit SDA = P2^4;
void tof250_i2c_read(unsigned char tof_ID,unsigned char word_adress, unsigned char *rdata, unsigned char num);
#endif
myiic.c
#include "myiic.h"
/*
*********************************************************************************************************
* 函 数 名: i2c_Delay
* 功能说明: I2C总线位延迟,最快400KHz
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{
unsigned char i;
/*
IIC 延时时间根据具体情况自行决定for循环延迟时间的大小
实际应用选择小于400KHz左右的速率即可
*/
for (i = 0; i < 10; i++);
}
void i2c_Start(void)
{
/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
SDA = 1;
SCL = 1;
i2c_Delay();
SDA = 0;
i2c_Delay();
SCL = 0;
i2c_Delay();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_Start
* 功能说明: CPU发起I2C总线停止信号
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{
/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
SDA = 0;
SCL = 1;
i2c_Delay();
SDA = 1;
i2c_Delay();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_WaitAck
* 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
* 形 参: 无
* 返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
unsigned char i2c_WaitAck(void)
{
unsigned char re; //应答信号等于0则应答正确,等于1则没有应答
SDA = 1; //释放总线,能让对方拉低
i2c_Delay();
SCL = 1; //此时刻开始,数据保持应答状态稳定
i2c_Delay();
if(SDA == 1)
{
re = 1; //没有应答
}
else
{
re = 0; //应答正确
}
SCL = 0;
i2c_Delay();
return re;
}
/*
*********************************************************************************************************
* 函 数 名: i2c_SendByte
* 功能说明: CPU向I2C总线设备发送8bit数据
* 形 参: _ucByte : 等待发送的字节
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(unsigned char _ucByte)
{
unsigned char i; //其实信号开始后SCL是被拉低的
for(i = 0; i < 8; i++)
{
if(_ucByte & 0x80)
SDA = 1;
else
SDA = 0;
SCL = 1;
i2c_Delay();
SCL = 0; //SCL等于0的时候写数据
if(i == 7) //最后一次时释放总线
{
SDA = 1;
}
_ucByte<<=1; //左移一位
i2c_Delay();
}
}
/*
*********************************************************************************************************
* 函 数 名: i2c_ReadByte
* 功能说明: CPU从I2C总线设备读取8bit数据
* 形 参: 无
* 返 回 值: 读到的数据
*********************************************************************************************************
*/
unsigned char i2c_ReadByte(void)
{
unsigned char i;
unsigned char value = 0;
for(i = 0; i < 8; i++)
{
value<<=1;
SCL = 1; //稳定状态的时候读数据
if(SDA == 1)
value++;
SCL = 0; //允许数据变化
i2c_Delay();
}
return value;
}
/*
*********************************************************************************************************
* 函 数 名: i2c_Ack
* 功能说明: CPU产生一个ACK信号
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
SDA = 0;//响应
i2c_Delay();
SCL = 1;
i2c_Delay();
SCL = 0;
i2c_Delay(); //在SCL为高电平期间SDA都为0即产生一个应答信号
SDA = 1; //释放总线
i2c_Delay();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_NAck
* 功能说明: CPU产生1个NACK信号
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
SDA = 1;
i2c_Delay();
SCL = 1;
i2c_Delay();
SCL = 0;
i2c_Delay(); //在SCL为高电平期间SDA都为1即产生一个非应答信号
}
void tof250_i2c_read(unsigned char tof_ID,unsigned char word_adress, unsigned char *rdata, unsigned char num)
{
unsigned char i;
i2c_Start();
i2c_SendByte(tof_ID << 1);
i2c_WaitAck();
i2c_SendByte(word_adress);
i2c_WaitAck();
i2c_Stop();
i2c_Delay();
i2c_Start();
i2c_SendByte(tof_ID << 1 | 0x01);
i2c_WaitAck();
if(num > 1){
for (i = 0; i < num - 1; i++) {
*(rdata + i) = i2c_ReadByte();
i2c_Ack();
}
}
*(rdata + num - 1) = i2c_ReadByte();
i2c_NAck();
i2c_Stop();
}
五、烧录说明
5.1 烧录接线示意图
5.2 烧录动态图
提示:烧录过程中请先断开TF250与STC12C5A60S2的TX\RX接线,否则无法正常烧录
六、结果输出
通过SSCOM串口软件打印结果(其他串口工具也可以)
提示:注意选择对应的波特率,此次测试使用波特率为9600