STM32CubeMX学习教程之十二:硬件I2C2读取SHT20温湿度并显示在LCD1602/LCD2004上(硬件I2C1连接)

完整源码下载:

https://github.com/simonliu009/STM32F10x-I2C-SHT20-LCD1602

本文是上一篇博客(https://blog.csdn.net/toopoo/article/details/80053929)的进阶。上一篇我们通过硬件I2C读取了SHT20的温湿度信息并且通过printf重定向到USART1串口打印信息。那么这一次是通过硬件I2C2读取SHT20温湿度并显示在LCD1602/LCD2004上(LCD1602/LCD2004通过硬件I2C1连接)。LCD2004的使用方法和LCD1602几乎完全一样,只是多了两行而已,只需要注意一下第三行和第四行的起始地址就好。

软件版本:

STM32CubeMX V4.25.0  

System Workbench V2.4
固件库版本:

STM32Cube FW_F1 V1.6.1

硬件:

OneNet 麒麟座V2.3

在STM32CubeMX中新建项目,选择正确的MCU型号(或者旧项目另存一下也可以)。

设置RCC, SYS,I2C1, I2C2,I2C的设置不需要改,用默认的值就好(默认速率为100KHz)。

 

打开串口USART1,串口设置也不需要修改,默认115200波特率。

 

 

 

然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M),如下图

 

引脚设置如下:

 

麒麟座V2.3 的 SHT20是接在I2C2上的,但是LCD1602如果需要用I2C方式连接,那么需要一块转接板(IO Expander),常用的是PCF8574, 我使用的是PCF8574AT。板子如下图:

直接焊接到LCD1602/LCD2004背面就可以,两者pin脚数量完全相同。

 

Project - setting ,ToolChain/IDE选择 SW4STM32,注意项目名称这里不能有空格,最好不要用中文。

 

 

勾选这里

 

 

保存以后,点击任务栏的生成代码图标

生成完毕以后在弹出的对话框点击"Open Project", System Workbench自动打开Eclipse并导入和打开了项目,然后展开项目树,

 

双击Src文件夹下的i2c.c, 照例我们需要修改那个bug,把I2C1和I2C2时钟初始化提前到GPIO初始化前面(注意两个都需要修改): 

/* USER CODE BEGIN I2C1_MspInit 0 */

__HAL_RCC_I2C1_CLK_ENABLE(); //提前初始化I2C时钟

  /* USER CODE END I2C1_MspInit 0 */

  

    /**I2C1 GPIO Configuration    

    PB6     ------> I2C1_SCL

    PB7     ------> I2C1_SDA 

    */

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C1 clock enable */

//    __HAL_RCC_I2C1_CLK_ENABLE();

  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */

  }

  else if(i2cHandle->Instance==I2C2)

  {

  /* USER CODE BEGIN I2C2_MspInit 0 */

__HAL_RCC_I2C2_CLK_ENABLE();//提前初始化I2C时钟

  /* USER CODE END I2C2_MspInit 0 */

  

    /**I2C2 GPIO Configuration    

    PB10     ------> I2C2_SCL

    PB11     ------> I2C2_SDA 

    */

    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C2 clock enable */

//    __HAL_RCC_I2C2_CLK_ENABLE();

  /* USER CODE BEGIN I2C2_MspInit 1 */

 

然后编辑main.c,首先我们需要用printf输出一些信息并重定向到串口,参考前面的教程,我们做如下修改:

 

/* USER CODE BEGIN PFP */


/* Private function prototypes -----------------------------------------------*/


#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
int getDigits(float d, int digits) //提取float的每位数字


{


int tempint = (int)(d / pow(10.0, digits - 1));


return (tempint % 10);


}


/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
PUTCHAR_PROTOTYPE{ HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch;}
/* USER CODE END 0 */

注意我们需要输出浮点数,所以还需要进行如下修改,右键点击项目,选择:

project properties > C/C++ Build > Settings > Tool Settings (TAB) > MCU GCC Linker > Miscellaneous > Linker flags

在把-specs=nosys.specs -specs=nano.specs 改为 -specs=nosys.specs -specs=nano.specs -u _printf_float

 

另外不要忘记把STM32Cube_FW_F1_V1.6.0\Projects\STM3210C_EVAL\Examples\UART\UART_Printf\syscalls.c 文件复制到Src目录

 

继续编辑main.c, 添加头文件和变量。

/* USER CODE BEGIN Includes */
#include "sht20.h"
#include "i2clcd.h"
#include "math.h" //pow()需要这个库
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
char t2;
char t1;
char tdec;
char rh2;
char rh1;
char rhdec;
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */

 /* USER CODE BEGIN 2 */
	lcd_init();
	lcd_clear();
	lcd_setCursor(1,0);
	lcd_send_string ("SHT20 LCD I2C Test");
	lcd_setCursor(2,1);
	lcd_send_string ("Author: SimonLiu");
	HAL_Delay(3000);
	lcd_clear();
	lcd_setCursor(0,0);
	lcd_send_string("Temp:");
	lcd_setCursor(0,1);
	lcd_send_string("RH:");
	HAL_Delay(1000);
	printf("\r\n Turning off backlight...\r\n");
	lcd_noBacklight();
	HAL_Delay(2000);
	printf("\r\n Turning ON backlight...\r\n");
	lcd_backlight();
	/* USER CODE END 2 */
	

while (1) {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
		

		SHT20_GetValue();
		printf( "Temperature:%0.1fC,  Humidity:%0.1f%%\r\n", sht20_info.tempreture, sht20_info.humidity);

		t2 = getDigits(sht20_info.tempreture,2) + 48;  //48 (or 0x30) is the ASCII code for 0.
		t1 = getDigits(sht20_info.tempreture,1) + 48;
		tdec = getDigits(sht20_info.tempreture,0) + 48;

		rh2 = getDigits(sht20_info.humidity,2) + 48;
		rh1 = getDigits(sht20_info.humidity,1) + 48;
		rhdec = getDigits(sht20_info.humidity,0) + 48;

		lcd_setCursor(6,0);
		lcd_send_data (t2);
		lcd_send_data (t1);
		lcd_send_data ('.');
		lcd_send_data (tdec);
		lcd_send_string ("C");

		lcd_setCursor(6,1);
		lcd_send_data (rh2);
		lcd_send_data (rh1);
		lcd_send_data ('.');
		lcd_send_data (rhdec);
		lcd_send_string ("%");


		HAL_Delay(1000);
	}
  /* USER CODE END 3 */

}

 

其中sht20.h和sht20.c 是基于麒麟座官方的例程移植的,原作者是张继瑞。

 

i2clcd.h和i2clcd.c 基于网络例程修改,来源 http://controllerstech.com/wp-content/uploads/2018/02/LCD-I2C.zip, 我增加了lcd_setCursor, lcd_clear,lcd_backlight, lcd_noBacklight命令。

int getDigits(float d, int digits) 函数用于提取每位数字用于LCD1602/LCD2004显示。

源码下载地址:https://github.com/simonliu009/STM32F10x-I2C-SHT20-LCD1602

右键点击项目,选择Properties, Run-Debug Settings, 点击右侧的New,在弹出对话框中选择Ac6 STM32 Debugging。

然后任务栏上点击Run图,当然会报错的,原因请查看另一篇我的博客(https://blog.csdn.net/toopoo/article/details/79680323),所以需要右键点击  项目名Run.cfg ,给它改个名字,

然后右键点击项目树里面的项目名称,选择“Propeties”,然后在Run/Debug Settings-选择项目名-Edit-Main-C/C++Application那里点击“Search Project”,然后选择出现的默认的elf文件:

然后在Debugger-User Defined-Browse 那里选择你自己改名的配置文件:

然后右键点击那个新的cfg文件,选择"Open With - Text Editor", 进行如下更改:

source [find interface/stlink.cfg] 更改为 source [find interface/stlink-v2.cfg]

reset_config srst_only srst_nogate connect_assert_srst 这一行改为 reset_config none 

然后再Run一下,就可以了。

注意在启动的时候,我做了一次背光开启和关闭的动作。不是软件bug,而是对背光控制命令的一个测试。

 

  • 6
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值