一、实验现象:
单片机通过USB-TTL模块与电脑连接,电脑通过串口调试助手来显示GY30光强传感器的测量值,实验结果如下:
对XCOM中三个数据的解释:BUF[0]、BUF[1]分别存放的是GY30模块采集到的光强数据的高八位和低八位,LUX是实测光强值,单位是勒克斯。
二、硬件准备:
实现本实验需要用到以下四个硬件:
STM32F103C8T6最小系统板、GY30模块、STLINK、USB-TTL模块。
三、接线:
使用的cubemx进行的初始化代码的配置,因此接线如配置图所示:
cube部分配置不做展示(因为只是开了一个I2C1和USART1),不过多赘述。
四、IIC通讯协议:
IIC通讯详细本人参考的下方链接(非本博主):
IIC原理超详细讲解---值得一看-CSDN博客
{ 图片借用一下(阿里嘎多!)}
主机发送数据简述: 起始信号,设备地址,主机写操作,从机应答,设备寄存器地址,从机应答,写入或发送的数据,从机应答,停止信号。(其中只有应答信号是从机向主机发送的,其他信号以及数据都是主机向从机发送的。)
主机读取数据简述:起始信号,设备地址,主机写操作,从机应答,设备寄存器地址,从机应答,起始信号,设备地址,主机读操作,从机应答,主机开始接收一字节数据,直到主机发送NO ACK(不再接收数据),主机发送停止信号。(读数据给我的感觉好像是,设备在自己干自己的活,你拍了拍他说,我想搁你这读个数据行不行,然后设备说行,你就洗耳恭听等他嘟嘟嘟把数据说完,然后你说OK阿里嘎多,你继续忙我走了,然后就结束了。)
五、GY30模块(BH1750传感器):
下图为BH1750,也就是GY30模块上搭载的光强传感器的指令集合,本实验初始化用到的指令只有其中两个,分别是:通电和连续H分辨率模式。因此在初始化时,需要对GY30写入数据0x01和0x10。
六、程序部分:
本实验采用CUBEMX+Keil5来进行实验,由于真的很简单(只用到了I2C1和USART1),因此配置部分不多赘述,如有需要请自行搜索。
串口需要重定向,CUBEMX生成程序后需要配置Keil下载程序时Reset and Run。
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void GY30_WR_CMD(uint8_t cmd) //GY30写操作
{
HAL_I2C_Master_Transmit(&hi2c1, 0x46, &cmd, 1, 1000);
}
void GY30_READ_DATA(uint8_t data[]) //GY30读取数据并储存
{
HAL_I2C_Master_Receive(&hi2c1, 0x46, data, 2, 0x100);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t BUF[2] = {0}; //定义数据缓冲区
uint16_t lux; //定义存放光强整合数据的变量
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
GY30_WR_CMD(0x01);
GY30_WR_CMD(0x10); //以上两步是对GY30进行初始化
HAL_Delay(180);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_I2C_Master_Receive(&hi2c1, 0x46, BUF, 2, 1000);
HAL_Delay(120);
lux = (BUF[0] << 8) + BUF[1]; //保存数据
lux /= 1.2; //光强计算
printf("BUF[0]:%d BUF[1]:%d LUX:%d LX\n\r", BUF[0],BUF[1],lux);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
主要用到了两个函数:HAL_I2C_Master_Transmit 和 HAL_I2C_Master_Receive。
HAL_I2C_Master_Transmit 函数的讲解可以看下面链接中视频的讲解。
3.HAL_I2C_Master_Transmit 函数解析_哔哩哔哩_bilibili
七、总结
对于IIC的学习,本次采用的是较为简单的模块,之前对于IIC,只是停留在了会用的层面,从来没有想过去理解一下IIC具体是怎么工作的,但是由于毕设需要用到IIC通讯的传感器,因此决定洗心革面,仔细学习一下IIC。
八、不足
本篇博客是有缺陷的,最明显的就是写入的设备地址我没有写,程序中有标明是0x46,但是在写程序之前上网上查了一下GY30的读写操作指令分别是0x46和0x47,开始写代码的时候没有查GY30的设备地址是多少,就以为是0x46,然后按照IIC的操作流程,对于设备没有寄存器(GY30应该是没有内部其他的寄存器吧..),只有设备地址的,只需要给设备地址然后选择读或写操作就OK,然后按照0x46的设备地址进行读和写操作,结果发现GY30可以正常工作hh,后知后觉感觉网上将0x46和0x47说成是读写指令不太准确,当ADDR空接或接地时GY30的设备地址应该就是0x46而非0x46是读指令,将上述两个十六进制数说成是读写指令的原因可能是没有使用HAL库进行IIC的配置而是采用模拟IIC的方式(臆想..)。HAL库IIC对于我来说最常用的目前来说应该是以下几个函数:HAL_I2C_Master_Transmit 、 HAL_I2C_Master_Receive 、 HAL_I2C_Mem_Write 、 HAL_I2C_Mem_Read,对于后两个函数具体如何理解以及使用,后续我会边学边写,持续记录。
工程链接:https://pan.baidu.com/s/1KqllUFF850fkP4dI-VF4tw?pwd=ncgf
提取码:ncgf
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_53925604/article/details/135886217
|