2024-06-11 05:19 PM
Hello there!
I am trying to get an stm8s003f3p6 to display text on an LCD1602 the LCD has the adapter board PCF8574 on it.
I'm using STVD and cosmic C compiler.
I used chatgpt to write the code and after quite a bit of tweaking i got it to compile and build and programmed to it the smt8xxx using STVP. It all seemed to go well.
I've connect the SCL pin (B4) and SDA pin (B5) from STM8xxx and 5V and GND on STM8xxx to the corresponding pins on the PCF8574.
The 1602 does light up but no text appears on it.
Here's the code and any help would be great!
Oh, i had to comment out the inline assembly command in the code in the delay function as the compiler didn't like it so maybe that causing the issue?
#include "stm8s.h"
#include "stm8s_i2c.h"
#include "stm8s_gpio.h"
#include "stm8s_clk.h"
// Define delay function prototypes
void delay_ms(uint16_t ms);
void delay_us(uint16_t us);
#define PCF8574_ADDRESS 0x4E // Adjust based on your PCF8574 address (usually 0x4E or 0x7E)
#define LCD_COMMAND 0x00
#define LCD_DATA 0x01
// LCD commands
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_ENTRY_MODE 0x04
#define LCD_DISPLAY_CONTROL 0x08
#define LCD_CURSOR_SHIFT 0x10
#define LCD_FUNCTION_SET 0x20
#define LCD_SET_CGRAM_ADDR 0x40
#define LCD_SET_DDRAM_ADDR 0x80
// Entry mode flags
#define LCD_ENTRY_RIGHT 0x00
#define LCD_ENTRY_LEFT 0x02
#define LCD_ENTRY_SHIFT_INCREMENT 0x01
#define LCD_ENTRY_SHIFT_DECREMENT 0x00
// Display control flags
#define LCD_DISPLAY_ON 0x04
#define LCD_DISPLAY_OFF 0x00
#define LCD_CURSOR_ON 0x02
#define LCD_CURSOR_OFF 0x00
#define LCD_BLINK_ON 0x01
#define LCD_BLINK_OFF 0x00
// Function set flags
#define LCD_8BIT_MODE 0x10
#define LCD_4BIT_MODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// Function prototypes
void My_I2C_Init(void);
void I2C_SendDataWrapper(uint8_t data);
void LCD_Send(uint8_t value, uint8_t mode);
void LCD_Command(uint8_t command);
void LCD_Char(char data);
void LCD_Init(void);
void My_I2C_Init(void) {
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
I2C_Init(I2C_MAX_STANDARD_FREQ, PCF8574_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);
I2C_Cmd(ENABLE);
}
void I2C_SendDataWrapper(uint8_t data) {
while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
I2C_GenerateSTART(ENABLE);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(PCF8574_ADDRESS, I2C_DIRECTION_TX);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(data);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(ENABLE);
}
void LCD_Send(uint8_t value, uint8_t mode) {
uint8_t highNibble = value & 0xF0;
uint8_t lowNibble = (value << 4) & 0xF0;
I2C_SendDataWrapper(highNibble | mode | 0x08); // Enable high nibble
I2C_SendDataWrapper(highNibble | mode); // Disable
I2C_SendDataWrapper(lowNibble | mode | 0x08); // Enable low nibble
I2C_SendDataWrapper(lowNibble | mode); // Disable
}
void LCD_Command(uint8_t command) {
LCD_Send(command, LCD_COMMAND);
}
void LCD_Char(char data) {
LCD_Send(data, LCD_DATA);
}
void LCD_Init(void) {
delay_ms(50);
LCD_Command(LCD_FUNCTION_SET | LCD_4BIT_MODE | LCD_2LINE | LCD_5x8DOTS);
LCD_Command(LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON | LCD_CURSOR_OFF | LCD_BLINK_OFF);
LCD_Command(LCD_CLEAR);
delay_ms(2);
LCD_Command(LCD_ENTRY_MODE | LCD_ENTRY_LEFT | LCD_ENTRY_SHIFT_DECREMENT);
}
void main(void) {
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
My_I2C_Init();
LCD_Init();
LCD_Command(LCD_SET_DDRAM_ADDR);
LCD_Char('H');
LCD_Char('e');
LCD_Char('l');
LCD_Char('l');
LCD_Char('o');
LCD_Char(' ');
LCD_Char('W');
LCD_Char('o');
LCD_Char('r');
LCD_Char('l');
LCD_Char('d');
while (1) {
// Main loop
}
}
void delay_us(uint16_t us) {
// Adjust this loop to achieve the desired delay
// This is a rough approximation and may need calibration
int i;
int j;
for (i = 0; i < us; i++) {
for (j = 0; j < 10; j++) {
// This loop will be optimized out if `volatile` is not used
// It ensures that the loop is not optimized out by the compiler
// __asm__("nop"); // No operation, 1 cycle
}
}
}
void delay_ms(uint16_t ms) {
while (ms--) {
delay_us(5000); // Assuming delay_us function provides 1 microsecond delay
}
}
2024-06-29 08:13 AM
If you decide to use "parallel interface" (3+4 pins) instead variant with I2C bridge then you can use my library: http://www.elektromys.eu/knihovny/stm8_hd44780_v20.zip
It runs in tens of applications of various users.