f3discovery:尝试将LCD屏幕1602与I2C模块一起使用

时间:2019-06-19 13:28:52

标签: c stm32 i2c hal

我正在尝试在stm32F3discovery上使用LCD屏幕。 屏幕由两行的16个LCD字符和一个I2C模块组成。

这是产品的链接: https://www.aliexpress.com/item/32763867041.html?spm=a2g0s.9042311.0.0.27424c4dsV7dLS

在屏幕背面,我可以看到书面:QAPASS 1602A 在I2C模块的芯片上,我可以看到写为:PCF8574T

这是芯片的数据表: https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf

我试图关注这个老师(与我想做的最接近): https://www.youtube.com/watch?v=1COFk1M2tak

我使用HAL库,发送数据的主要功能是“ HAL_I2C_Master_Transmit”。

这是“ HAL_I2C_Master_Transmit”中功能的描述:

  • @brief在主控模式下以阻止模式传输大量数据。
  • @param hi2c指向I2C_HandleTypeDef结构的指针,该结构包含指定I2C的配置信息。
  • @param DevAddress目标设备地址:调用接口之前,数据表中的设备7位地址值必须向左移动
  • @param pData指向数据缓冲区的指针
  • @param大小要发送的数据量
  • @param超时超时持续时间
  • @retval HAL状态

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef * hi2c,uint16_t DevAddress,uint8_t * pData,uint16_t Size,uint32_t超时)

//I initialise a buffer
//I use a for loop to find the address of my slave: 0x3D (even tho on the //datasheet it's 0x3F, looks like A1 is bridged :O )
//I use the HAL_I2C_Master_Transmit function
//I move the address one bit to the left
//I reuse the HAL_I2C_Master_Transmit
//Nothing happens on the screen

//Here is my code (I tried to remove the useless comments):

#include "main.h"

I2C_HandleTypeDef hi2c1; // Init generated bu CubeMX
SPI_HandleTypeDef hspi1; // Init generated bu CubeMX
PCD_HandleTypeDef hpcd_USB_FS; // Init generated bu CubeMX

uint16_t adresseLCD; // the variable I put the slave address on
uint8_t buffer[]="123"; // The buffer I wanna see on the screen

void SystemClock_Config(void); // Generated by CubeMX
static void MX_GPIO_Init(void); // Generated by CubeMX
static void MX_I2C1_Init(void); // Generated by CubeMX
static void MX_SPI1_Init(void); // Generated by CubeMX
static void MX_USB_PCD_Init(void); // Generated by CubeMX

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    MX_USB_PCD_Init();

    adresseLCD=0x3D;
    HAL_I2C_Master_Transmit(&hi2c1, adresseLCD, buffer, 1, 1000);

    adresseLCD=adresseLCD*2; // Yes I could have used "adresseLCD<<1" but I 
    //am not used to that
    HAL_I2C_Master_Transmit(&hi2c1, adresseLCD, buffer, 1, 1000);

    while(1)
    {
    }
}

我希望屏幕上会显示一些东西(甚至是随机值),但是什么也没有出现(尽管它会亮起)。 我没有错误(只有警告,因为我在WritePIn时使用“ 1”而不是“ Pin_ON”)

2 个答案:

答案 0 :(得分:1)

您期望它是错误的。

首先,将I2C模块焊接在背面,它只是简单的串行到并行转换器。当您在I2C总线上写入数据时,它将根据数据字节中的8个接收位设置其8个输出。当您读取数据字节时,它将切换到输入模式并在8个引脚上读取逻辑电平,并通过串行线进行传输。您可以在提供的datasheet on PCF8574中阅读更详细的说明。

即此部分不会执行任何“魔术”操作,该操作会将输入的字符输入并显示出来。这意味着随机数据的输出是徒劳的。

您还需要了解两件事:

  1. 该模块如何连接到显示驱动器
  2. 使用哪种显示驱动程序以及如何使用它。

第一个问题的答案可能在Internet上找到: I2C LCD module schematic(摘自here

您可以看到显示器以4位模式连接,输出 P4-P7 (即,您以数据字节的四个最高有效位传输的内容)已连接到显示器的数据线,输出 P0-P2 连接到控制线 RS R / W EH P3 用于控制背光。

知道了这一点,我们提出了第二个问题。我只能提出建议,但您的显示模块上很有可能装有Hitachi HD44780 IC。在其上的datasheet中,您可以找到有关应该在控制线上输出哪些数据的信息。

您可以在第8页上找到引脚说明:

  • RS 选择命令(0)还是数据(1)
  • R / W 选择写操作(0)还是读操作(1)
  • E 实际上是一个闪光灯。在下降沿,即当它从1变为0时,显示驱动器从数据线读取数据。这意味着要传递4位数据,您应该执行2次写入操作:首先将第2位设置为高,然后将所有其他位设置为高,但是将第2位设置为零。

现在,您可以阅读数据表第25页的说明列表。第46页的4位模式的初始化序列(图24)。请注意,对于每一行位,您实际上都发送2个数据字节:高2位高,然后低2位。

请注意,在4位模式下,所有命令和数据均包含两个写入阶段:首先-字节的上半部分,然后是字节的下半部分。每个阶段都是2次向I2C模块写入数据,E位为高和低,即,您需要发送4个字节以输出1个字节的数据。

答案 1 :(得分:0)

因此,基本上为了将数据从STM32传输到LCD显示驱动器(HD44780),您需要通过I2C接口芯片(PCF8574)模拟后者的接口信号。

换句话说,MCU将发送I2C命令,该命令将切换I2C“背包”芯片,从而应模拟LCD驱动器的 right 信号。

当您使用HAL_I2C_Master _ *()方法时,发生这种情况很容易。在缓冲区阵列中,您可以根据需要以[0],[1],[2] ...等顺序指定LCD上引脚的状态。例如,假设我们有DB [7: [4]连接到PCF I2C扩展器的高4位。我们可以设置以下内容:

buffer[0] = 0xD0 ; // 0b11010000;
buffer[1] = 0xA0 ; // 0b10100000;
buffer[2] = 0xF0 ; // 0b11110000;

HAL_I2C_Master_Transmit(&hi2c1, adresseLCD, buffer, 3, 10); // Note 3 bytes are sent

一旦准备好缓冲区,HAL_I2C_Master_Transmit()调用将连续发送树字节,从而像您提到的那样切换DB引脚:

DB7: 1 -> 1 -> 1
DB6: 1 -> 0 -> 1
DB5: 0 -> 1 -> 1
DB4: 1 -> 0 -> 1

这可以应用于PCF芯片上的所有8个引脚。还要注意的是,这种顺序的IO更新还减少了I2C通信开销,因为它只寻址一次I2C从芯片:)。


顺便说一句,我目前正在通过I2C库在STM32F1xx的LCD上工作(可能会适合其他STM32F系列)。您可以在github上查看它(仍然是WIP):

https://github.com/meteowrite/stm32_i2cLcd

欢呼