Question
lcd1602+i2c+nucleo f401re don't work on stm32cubeide but works on keil uvision
I run the same code with the same .ioc between stme32cubeide and keil uvision but lcd only show on keil and it shows nothing on cubeide. Anyone know why?
I use register due to requirement of my teacher.
Thank you!
#include "stm32f4xx.h"
#inclide < stdio.h>
#define LCD_ADDR (0x27 << 1)
#define LCD_EN 0x04
#define LCD_RS 0x01
void Timer2_Init(void)
{
// Clock enable
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
}
void delay_us(uint32_t us)
{
// Prescaler
TIM2->PSC = 16 - 1;
// Auto-reload value
TIM2->ARR = us;
// Forced update
TIM2->EGR = TIM_EGR_UG;
// Clear update flag
TIM2->SR &= ~TIM_SR_UIF;
// Timer enable
TIM2->CR1 |= TIM_CR1_CEN;
while (!(TIM2->SR & TIM_SR_UIF))
; // wait till update flag is set
// Clear update flag
TIM2->SR &= ~TIM_SR_UIF;
// Stop timer
TIM2->CR1 &= ~TIM_CR1_CEN;
}
void I2C_Init(void)
{
// Clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
// Analog mode
GPIOB->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1;
// Open drain
GPIOB->OTYPER |= GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9;
// High speed output
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9;
// Pull up resistor
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0 | GPIO_PUPDR_PUPDR9_0;
// Alternative function for i2c
GPIOB->AFR[1] |= (4 << (4 * 0)) | (4 << (4 * 1));
// Reset I2C
I2C1->CR1 |= (1 << 15);
I2C1->CR1 &= ~(1 << 15);
// I2C clock bus
I2C1->CR2 |= (42 << 0);
I2C1->CCR = 210 << 0;
I2C1->TRISE = 43;
// I2C enable
I2C1->CR1 |= I2C_CR1_PE;
}
void I2C_SendData(uint8_t address, uint8_t data)
{
// Acknowlegde enable
I2C1->CR1 |= I2C_CR1_ACK;
// Send start signal
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB))
; // wait for start condition generation
// Send slave address
I2C1->DR = address;
while (!(I2C1->SR1 & I2C_SR1_ADDR))
; // wait for address matched
// Dummy read the register to clear it before sending data
(void)I2C1->SR1;
(void)I2C1->SR2;
// Send data
while (!(I2C1->SR1 & I2C_SR1_TXE))
; // wait for data register is empty
I2C1->DR = data;
while (!(I2C1->SR1 & I2C_SR1_BTF))
; // wait for byte transfer
// Send stop signal
I2C1->CR1 |= I2C_CR1_STOP;
}
void LCD_SendCmd(uint8_t cmd)
{
uint8_t data_u, data_l;
uint8_t data_t[4];
data_u = (cmd & 0xf0);
data_l = ((cmd << 4) & 0xf0);
data_t[0] = data_u | 0x0C; // en=1, rs=0
data_t[1] = data_u | 0x08; // en=0, rs=0
data_t[2] = data_l | 0x0C; // en=0, rs=0
data_t[3] = data_l | 0x08; // en=1, rs=0
for (int i = 0; i < 4; i++)
{
I2C_SendData(LCD_ADDR, data_t[i]);
delay_us(20);
}
}
void LCD_SendData(uint8_t data)
{
uint8_t data_u, data_l;
uint8_t data_t[4];
data_u = (data & 0xf0);
data_l = ((data << 4) & 0xf0);
data_t[0] = data_u | 0x0D; // en=1, rs=1
data_t[1] = data_u | 0x09; // en=0, rs=1
data_t[2] = data_l | 0x0D; // en=1, rs=1
data_t[3] = data_l | 0x09; // en=0, rs=1
for (int i = 0; i < 4; i++)
{
I2C_SendData(LCD_ADDR, data_t[i]);
delay_us(20);
}
}
void LCD_Init(void)
{
LCD_SendCmd(0x33); // LCD 4-bit mode
delay_us(10000);
LCD_SendCmd(0x32); // LCD 4-bit mode
delay_us(2000);
LCD_SendCmd(0x06); // Cursor position auto increment after a character write
delay_us(2000);
LCD_SendCmd(0x0C); // No cursor and cursor blinking
delay_us(2000);
LCD_SendCmd(0x28); // 2 line mode and 5x8 mode
delay_us(2000);
LCD_SendCmd(0x01); // Clear screen
delay_us(2000);
}
void LCD_PutString(char *string, int line)
{
if (line == 1)
{
LCD_SendCmd(0x80); // First line
}
else
{
LCD_SendCmd(0xC0); // Second line
}
while (*string)
{
LCD_SendData((uint8_t)(*string));
string++;
}
}
void LCD_PutStringFloat(char *string, float value, int line)
{
char buffer[32];
sprintf(buffer, "%s%.1f", string, value);
LCD_PutString(buffer, line);
}
int main()
{
Timer2_Init();
I2C_Init();
LCD_Init();
delay_us(100000);
LCD_PutString("Hello", 1);
while (1)
{
}
}
