【STM32F103ZE】TOF250(IIC)基于STM32系列开发板的运用

7 篇文章 0 订阅
2 篇文章 0 订阅

一、前言

此片文章主要介绍如果通过STM32系列开发板来读取TOF250(IIC接口)数据的教程
提示:以下的案例仅供参考学习使用


二、硬件准备

  • TOF250 :测距传感器

  • STM32系列开发板:STM32F103ZE 主频8M
    提示:STM32系列开发板种类较多,此次测试使用的是普中科技的PZ6806L开发板,其他类型STM32开发板程序可能会有略微差异
    <img src="https://img-blog.csdnimg.cn/bbfecce49e5a4430b6b1367a9aa57c54.png

详细资料可以参考:STC 官网

  • 电脑 :Windows 7/10/11

  • 杜邦线:各类(若干)
    在这里插入图片描述

  • TOF250尾线:购买时自带有一根尾线
    在这里插入图片描述


二、软件准备

  • KEIL IDE:参考官网下载安装教程
    在这里插入图片描述
  • 烧录软件:PZ-ISP V1.86 普中科技

三、硬件接线图

在这里插入图片描述

说明:

  • 此次测试仅使用的是模拟IIC,方便理解
  • USB打印结果需要用到串口1的TX

四、例程源码

main.c

/**************************************************************
**技术论坛:https://blog.csdn.net/HCJ_Application/article/details/124058266
**修改日期:2022/4/27
**技术说明:基于STM32F103ZET6单片机,主频8M
**版本:V1.0
**作者:深圳市弘成基科技有限公司
**************************************************************/

#include "sys.h"
#include "delay.h"
#include "usart.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 RxData[10];          //IIC接口接收数据区


unsigned int  Tof250_dist = 0;         //读取到TOF250的具体数值

int main(void)
{
    //unsigned char y;
    __I2C_Status_TypeDef i2CStatus;
//    u16 len;                           //检测每次接收到的长度,方便字符串转整数的时候进行处理
    User_I2C_Init(); //IIC初始化
    delay_init();
    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

    /**************************************************************
    **TOF250串口通信协议:
    **波特率 : 9600
    **数据位 : 8
    **校验   : 无
    **停止位 : 1
    ****************************************************************/
    uart_init(9600);	 //串口初始化为115200
    while(1)
    {
        i2CStatus = I2C_RecvBytes(TOF250_ID,TOF250_DIST_H, &RxData[0], 2,100);    //通过IIC读取TOF250距离值信息
        if(i2CStatus == I2C_OK) {
            Tof250_dist = RxData[1] + RxData[0]*256;
            printf("%u cm\n",Tof250_dist);
        }
        delay_ms(100);                                      //延时100ms,TOF250默认更新速度10HZ
    }
}

usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收

extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA;         		//接收状态标记
//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);
#endif

usart.c

#include "sys.h"
#include "usart.h"	  
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

myiic.c

#include "myiic.h"
/*************************************************
Function: User_I2C_Init
Description: config I2C 
*************************************************/
void User_I2C_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 输出高

}

/*************************************************
Function: delay
Description: 
Input:  Delaycnt - delay cnt
*************************************************/
void delay(uint32_t Delaycnt)
{
	uint32_t i;
	
	for(i = 0; i<Delaycnt; i++)
	{
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	}
}

/*************************************************
Function: I2C_GenerateStart
Description: 
*************************************************/
static void I2C_GenerateStart(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
    delay(5);
   IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    delay(5);
    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
    delay(5);
}
/*************************************************
Function: I2C_GenerateStop
Description: 
*************************************************/
static void I2C_GenerateStop(void)
{
		IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
    delay(5);  
	IIC_SCL=1; 
    delay(5); 
	IIC_SDA=1;  
    delay(5); 
}
/*************************************************
Function: I2C_GenerateAck
Description: 
*************************************************/
static void I2C_GenerateAck(__I2C_ACK_TypeDef ack)
{
    if(ack == I2C_NACK) 
	{
        IIC_SDA=1;
	}
    else
	{
        IIC_SDA=0;;
	}
	
    delay(5);		
    IIC_SCL=1;
    delay(5);
    IIC_SCL=0;
		delay(5);
}
/*************************************************
Function: I2C_RecvAck
Description: 
*************************************************/
static __I2C_ACK_TypeDef I2C_RecvAck(uint32_t Timeout)
{
	uint32_t timeout = 0;
    __I2C_ACK_TypeDef ackStatus;
	
	IIC_SDA=1;
	SDA_IN();
    delay(5);
	IIC_SCL=1;
    delay(5);
	
	while(1)
	{
		ackStatus = (READ_SDA == Bit_RESET) ? I2C_ACK : I2C_NACK;
		if(ackStatus == I2C_ACK)
		{
			break;
		}
		
		if((timeout++) > Timeout)
		{
			ackStatus = I2C_NACK;
			break;
		}
	}

    IIC_SCL=0;
    delay(5);
    //SDA_OUT();
    return ackStatus;  
}
/*************************************************
Function: I2C_SendByte
Description: 
*************************************************/
static __I2C_ACK_TypeDef I2C_SendByte(uint8_t data, uint32_t Timeout)
{
    uint8_t i;
	
    IIC_SCL=0;
	
    for (i = 0; i < 8; i++)      
    {
				SDA_OUT();
        if((data << i)&0x80)
        {
            IIC_SDA=1;
        }
        else 
        {
            IIC_SDA=0;;
        }
        delay(5); 
        IIC_SCL=1;               
        delay(5);             
        IIC_SCL=0;    
        delay(5);   
    }

    return I2C_RecvAck(Timeout);
}
/*************************************************
Function: I2C_RecvByte
Description: 
*************************************************/
static uint8_t I2C_RecvByte(void)
{
    uint8_t i;
    uint8_t data = 0, BitStatus = 0;
    
    IIC_SDA=1;
		SDA_IN();
    delay(5);
    for (i = 0; i < 8; i++)
    {  
        data <<= 1;
        IIC_SCL=1; 
        delay(5); 
		
        BitStatus = (READ_SDA == Bit_SET) ? 1 : 0;
        data |= BitStatus;     
		
        IIC_SCL=0;
        delay(5);
    }
	
	SDA_OUT();
    return data;
}
/*************************************************
Function: I2C_DummyWrite
Description: I2C DummyWrite
*************************************************/
static __I2C_Status_TypeDef I2C_DummyWrite(uint8_t SlaveAddr, uint8_t RegAddr, uint8_t OperLen, uint32_t Timeout)
{
	/* Generate Start Sign */
	I2C_GenerateStart();
	
	/* Send Slave Address */
	if(I2C_SendByte((SlaveAddr<<1) | I2C_Transmitter, Timeout) != I2C_ACK)
	{
		I2C_GenerateStop();
		return I2C_ERROR;
	}

//	/* Send RegAddr_H */
//	if(I2C_SendByte((RegAddr >> 8) & 0xFF, Timeout) != I2C_ACK)
//	{
//		I2C_GenerateStop();
//		return I2C_ERROR;
//	}
	
//	/* Send RegAddr_L */
//	if(I2C_SendByte(RegAddr & 0xFF, Timeout) != I2C_ACK)
//	{
//		I2C_GenerateStop();
//		return I2C_ERROR;
//	}
//	
		/* Send RegAddr */
	if(I2C_SendByte(RegAddr , Timeout) != I2C_ACK)
	{
		I2C_GenerateStop();
		return I2C_ERROR;
	}
	
//	/* Send Data length */
//	if(I2C_SendByte(OperLen, Timeout) != I2C_ACK)
//	{
//		I2C_GenerateStop();
//		return I2C_ERROR;
//	}

	return I2C_OK;
}


/*************************************************
Function: I2C_RecvBytes
Description: I2C SendBytes
*************************************************/
__I2C_Status_TypeDef I2C_RecvBytes(uint8_t SlaveAddr, uint8_t RegAddr, uint8_t *Rxbuf, uint8_t OperLen, uint32_t Timeout)
{
	uint8_t i = 0;
	
	/* Dummy Write */
	if(I2C_DummyWrite(SlaveAddr, RegAddr, OperLen, Timeout) != I2C_OK)
	{
		I2C_GenerateStop();
		return I2C_ERROR;
	}

	/* Generate Start Sign */
	I2C_GenerateStart();
	
	/* Send Slave Address */
	if(I2C_SendByte((SlaveAddr<<1) | I2C_Receiver, Timeout) != I2C_ACK)
	{
		I2C_GenerateStop();
		return I2C_ERROR;
	}
	
	/* Receive Data */
	for(i = 0; i < OperLen - 1; i++)
	{
		Rxbuf[i] = I2C_RecvByte();
		I2C_GenerateAck(I2C_ACK);
	}

	Rxbuf[OperLen - 1] = I2C_RecvByte();
	I2C_GenerateAck(I2C_NACK);
	
	/* Generate Stop Sign */
	I2C_GenerateStop();
	
	return I2C_OK;
}

myiic.h

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"

#define USER_I2C_SCL_PIN  GPIO_Pin_6
#define USER_I2C_SDA_PIN  GPIO_Pin_7
#define USER_I2C_GPIO     GPIOB

//IO方向设置
 
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

//IO操作函数	 
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA	 
#define READ_SDA   PBin(7)  //输入SDA 

typedef enum
{
	I2C_OK = 0U,
	I2C_BUSY = 1U,
	I2C_TIMEOUT = 3U,
	I2C_ERROR = 4U,
}__I2C_Status_TypeDef;

typedef enum
{
	I2C_ACK = 0U,
	I2C_NACK = 1U,
}__I2C_ACK_TypeDef;

typedef enum
{
	I2C_Transmitter = 0U,
	I2C_Receiver = 1U,
}__I2C_Oper_TypeDef;

typedef enum
{
	I2C_SDA_IN = 0U,
	I2C_SDA_OUT = 1U,
}__I2C_SDAMode_TypeDef;
/*************************************************
Function: User_I2C_Init
Description: config I2C 
*************************************************/
void User_I2C_Init(void);

/*************************************************
Function: delay
Description: 
Input:  Delaycnt - delay cnt
*************************************************/
void delay(uint32_t Delaycnt);

/*************************************************
Function: I2C_SendBytes
Description: I2C SendBytes
*************************************************/
__I2C_Status_TypeDef I2C_SendBytes(uint8_t SlaveAddr, uint8_t RegAddr, uint8_t *TxBuf, uint8_t OperLen, uint32_t Timeout);

/*************************************************
Function: I2C_RecvBytes
Description: I2C SendBytes
*************************************************/
__I2C_Status_TypeDef I2C_RecvBytes(uint8_t SlaveAddr, uint8_t RegAddr, uint8_t *Rxbuf, uint8_t OperLen, uint32_t Timeout);
unsigned char tof250_i2c_read(unsigned char tof_ID,unsigned char word_adress, unsigned char *rdata, unsigned char num);
#endif

五、烧录说明

5.1 烧录接线示意图

在这里插入图片描述

5.2 烧录动态图

请添加图片描述


六、结果输出

通过SSCOM串口软件打印结果(其他串口工具也可以)

提示:注意选择对应的波特率,此次测试使用波特率为9600
请添加图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值