我正在尝试在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”中功能的描述:
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”)
答案 0 :(得分:1)
您期望它是错误的。
首先,将I2C模块焊接在背面,它只是简单的串行到并行转换器。当您在I2C总线上写入数据时,它将根据数据字节中的8个接收位设置其8个输出。当您读取数据字节时,它将切换到输入模式并在8个引脚上读取逻辑电平,并通过串行线进行传输。您可以在提供的datasheet on PCF8574中阅读更详细的说明。
即此部分不会执行任何“魔术”操作,该操作会将输入的字符输入并显示出来。这意味着随机数据的输出是徒劳的。
您还需要了解两件事:
第一个问题的答案可能在Internet上找到: (摘自here)
您可以看到显示器以4位模式连接,输出 P4-P7 (即,您以数据字节的四个最高有效位传输的内容)已连接到显示器的数据线,输出 P0-P2 连接到控制线 RS , R / W , EH 和 P3 用于控制背光。
知道了这一点,我们提出了第二个问题。我只能提出建议,但您的显示模块上很有可能装有Hitachi HD44780 IC。在其上的datasheet中,您可以找到有关应该在控制线上输出哪些数据的信息。
您可以在第8页上找到引脚说明:
现在,您可以阅读数据表第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
欢呼