2024-12-10 07:01 AM
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)
{
}
}
2024-12-10 07:12 AM
Have you used an oscilloscope and/or logic analyser to compare what's happening on the wires in the 2 cases?
Have you used the debuggers in the IDEs to compare what's happening within the code in the 2 cases?
2024-12-10 10:33 AM
Is using CubeIDE a requirement? Otherwise just use Keil and be happy.
There are differences in runtime libraries, compiler-specific behaviors (optimization) and so on. Save your time and nerve cells for the meaningful part of your project.
2024-12-10 10:40 AM
This is true but, when a project works on one IDE and not another, that's usually an indicator of problems in the code...
2024-12-10 02:38 PM
Nothing particularly is jumping out in a KEIL vs GNU sense
I'd probably simplify the micro-second delay stuff to initialize the counter once, in maximal 32-bit mode and then observe the delta in TIM2->CNT
Check the peripheral registers in one vs the other.
Check the I2C traffic with a logic-analyzer, type to understand if the issue is one of timing or signalling.
Confirm it's executing.
Ideally have a serial connection or SWV working so you can output diagnostic info in real-time