Closed Basti3DB closed 3 years ago
At least some delay cases are not implemented. At least for testing you should use some delay instead of NOP. 3wire is also a little bit complicated. I personally would first test with 4wire spi.
Regarding the 3wire interface: It is the responsibility of the byte procedure to convert the 9 bit stream into a byte stream. It may look like this: https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_byte.c#L279
Another implementation (which will use the Arduino SPI interface) is here:
https://github.com/olikraus/u8g2/blob/3c6460a73f7f310c665cef0af1d2bac49bf6c655/cppsrc/U8x8lib.cpp#L758-L765
this includes a call to arduino_hw_spi_3w_sendbyte
where most of the additional conversion magic is done.
Another option is to ask your SPI hardware subsystem to send 9 instead of 8 bytes, if this is supported by your SPI hardware. Especially the line 'hspi1.Init.DataSize = SPI_DATASIZE_8BIT;' needs to be different I assume. Additionally you still have to construct the 9 bit token and provide the same to your hardware subsystem, so the BYTE_SEND code will be more complex:
case U8X8_MSG_BYTE_SEND:
//HAL_SPI_Transmit(&hspi1,(uint8_t *) arg_ptr, arg_int, 1000);
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *) arg_ptr, arg_int);
break;
As a conclusion, your code can not work, because the 9 to 8 bit conversion is missing.
So in order to make things simpler, i did change the display connection to use 4 Wire SPI. That means the CD Bit is now a seperate wire. Also the SPI data length is no more 9 bit, but 8 bit.
In the delay fuctions i changed the nop to 1 ms delay, but in debug mode i noticed they were not called. Only the "U8X8_MSG_DELAY_MILLI" is called.
uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8,U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int,
U8X8_UNUSED void *arg_ptr) {
switch (msg) {
case U8X8_MSG_GPIO_AND_DELAY_INIT: //Initialize SPI peripheral
// HAL initialization contains all what we need so we can skip this part.
HAL_Delay(1);
break;
case U8X8_MSG_DELAY_MILLI: //Function which delay arg_int * 1ms
HAL_Delay(arg_int);
break;
case U8X8_MSG_DELAY_10MICRO: //Function which delay 10us
HAL_Delay(1);
//__NOP();
break;
case U8X8_MSG_DELAY_100NANO: //Function which delay 100ns
HAL_Delay(1);
//__NOP();
break;
case U8X8_MSG_DELAY_NANO: //Function which delay 1ns
HAL_Delay(1);
//__NOP();
break;
//Function to define the logic level of the clockline
case U8X8_MSG_GPIO_SPI_CLOCK:
if (arg_int)
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, RESET);
else
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, SET);
break;
//Function to define the logic level of the data line to the display
case U8X8_MSG_GPIO_SPI_DATA:
if (arg_int)
HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, SET);
else
HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, RESET);
break;
// Function to define the logic level of the CS line
case U8X8_MSG_GPIO_CS:
if (arg_int)
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, RESET);
else
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, SET);
break;
//Function to define the logic level of the Data/ Command line
case U8X8_MSG_GPIO_DC:
if (arg_int) HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, SET);
else HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, RESET);
break;
//Function to define the logic level of the RESET line
case U8X8_MSG_GPIO_RESET:
if (arg_int)
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, SET);
else
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, SET);
break;
default:
return 0; //A message was received which is not implemented, return 0 to indicate an error
}
return 1; // command processed successfully.
}
Ony my Oszi i can see the Data is not changing very often and the clock is not seperated into 8 bit bursts.
My send function now looks like this:
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr) {
switch (msg) {
case U8X8_MSG_BYTE_SEND:
HAL_SPI_Transmit(&hspi1,(uint8_t *) arg_ptr, arg_int, 100);
//HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*) arg_ptr, arg_int);
break;
case U8X8_MSG_BYTE_INIT:
break;
case U8X8_MSG_BYTE_SET_DC:
HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, SET);
//__NOP();
break;
case U8X8_MSG_BYTE_END_TRANSFER:
//__NOP();
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, RESET);
break;
default:
return 0;
}
return 1;
}
Did you also change the Interface type of the display to 4 wire SPI?
You mean in my init function?
printf("********LCD SETUP BEGIN********\n");
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, RESET);
HAL_Delay(5);
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, SET);
HAL_Delay(2);
//u8g2_Setup_st7920_p_128x64_1(&u8g2, U8G2_R0, u8x8_byte_3wire_sw_spi, u8g2_gpio_and_delay_stm32);
//u8g2_Setup_uc1608_erc240120_f(&u8g2, U8G2_R0, u8x8_byte_3wire_sw_spi, u8g2_gpio_and_delay_stm32);
u8g2_Setup_uc1608_erc240120_f(&u8g2, U8G2_R2, u8x8_byte_4wire_hw_spi,u8g2_gpio_and_delay_stm32);
HAL_Delay(500);
LCD_setup();
HAL_Delay(500);
printf("********LCD SETUP END********\n");
Yes i changed it and also checked with debug and its called.
Is it right to only change the argumet in this setup (u8g2_Setup_uc1608_erc240120_f)?
No, the display itself.
Yes i did. I rewired the BM0 and BM1 pins to GND. Also the D7 pin is HIGH, D6 LOW. So S8 mode is selected.
i wonder if its corret, in the HAL_SPI_Transmit function call:
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr) {
switch (msg) {
case U8X8_MSG_BYTE_SEND:
if(HAL_SPI_Transmit(&hspi1,(uint8_t *) arg_ptr, arg_int, 100) != HAL_OK) printf("SPI error\n");
//HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*) arg_ptr, arg_int);
break;
case U8X8_MSG_BYTE_INIT:
break;
case U8X8_MSG_BYTE_SET_DC:
HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, SET);
//__NOP();
break;
case U8X8_MSG_BYTE_END_TRANSFER:
//__NOP();
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, RESET);
break;
default:
return 0;
}
return 1;
}
there the input arguments are:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
but when i debug and watch the arg_int(which is the size) variable i see it is mostly 1(dec) and a few times it is 240(dec).
In my opinion it make sense if it is a 8, because of the 8 bit SPI data?
The size is provided in bytes. So 1 means 1 byte.
so i now have debugged a lot and can now see the data beeing send to the display, but still shows nothing. In this spi routing i added the "while" statement to wait til previous data is send, but no improvement
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr) {
switch (msg) {
case U8X8_MSG_BYTE_SEND:
while(!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));
if(HAL_SPI_Transmit(&hspi1,(uint8_t *) arg_ptr, arg_int, 100) != HAL_OK) printf("SPI error\n");
//HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*) arg_ptr, arg_int);
break;
....
in the SPI data i see, the Clock, CS and DC signal to be ok. there is only data been send while dc is low, so it means only instructions are send. when dc is high (so screen data) there is no "movement" on the data line.
Do you have any idea why this occurs?
I do not know anything on your HAL functions, but
if (arg_int) HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, SET);
else HAL_GPIO_WritePin(LCD_CD_GPIO_Port, LCD_CD_Pin, RESET);
did look better to me. One more point: Did you init the CD (DC) pin corrently as output pin? You had added this pin during the change from 3wire to 4wire...
I changed those to lines, but nothing on the display.
Yes, i think the CD pin is init correctly, those init functions are generated automatic from the CUBE IDE.
While debugging i noticed, the arg_ptr variable, which should hold the data to send, actually holds the right data. Think this because the one variable counts up, which is also in the arg_ptr...
void LCD_send_screen(void) {
yPos++;
if(yPos > 100)yPos = 0;
u8g2_ClearBuffer(&u8g2);
u8g2_DrawLine(&u8g2, 50,yPos, 100, yPos);
u8g2_SetFont(&u8g2, u8g2_font_lastapprenticebold_tr);
u8g2_DrawStr(&u8g2, 10, 20, "Uff");
u8g2_SendBuffer(&u8g2);
}
with arg_ptr i mean this:
uint8_t *txdata;
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr) {
switch (msg) {
case U8X8_MSG_BYTE_SEND:
txdata = (uint8_t*)arg_ptr;
printf("arg_ptr: %x\n",txdata); // THIS VARIABLE
while(!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));
if(HAL_SPI_Transmit(&hspi1,(uint8_t *) &arg_ptr, arg_int, 100) != HAL_OK) printf("SPI error\n");
//HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*) arg_ptr, arg_int);
break;
in the Inline debuggin i see that at the pointer memory addr. is the "changing" data but i dont think, the "real" variable data is transferd, i think, what the debug prints, is only the memory addr. of this variable. How can i change this behavior?
yes arg_ptr is a memory location with arg_int bytes in case of MSG_BYTE_SEND.
Your question is more regarding HAL_SPI_Transmit, which I do not know. I can just guess, that you have to provide a memory location as second argument. In this case you must not apply & to arg_ptr, because arg_ptr already is the memory location (and it does not make sense to calculate the memoy location of the variable which holds the memory location), so
HAL_SPI_Transmit(&hspi1,(uint8_t *) arg_ptr, arg_int, 100)
would be correct. However, reading https://community.st.com/s/question/0D50X00009kKdg5/halspitransmit-size-is-it-defined-as-a-byte-or-a-word seems to say, that the second argument actually expects an array of words instead of an array of bytes. If this is the case, than you need to convert the array of bytes (which is provided in arg_ptr) into an array of words for your HAL function.
Maybe as a first step try to transfer only one byte at a time in a loop:
while( arg_int > 0 ) {
HAL_SPI_Transmit(&hspi1,arg_ptr++, 1, 100);
arg_int--;
}
I finally got it working!
As a conclusion i can say:
u8g2_SetContrast(&u8g2, 85);
Many thanks for your great support and helping me out ;)
:-)
Hello all,
I am working on a project including the ERC240120 LCD. I already did this with my Arduino MEGA and everything works perfektly fine. Now i am struggling with Flash and Ram so i decided to switch to the STM32 platform (STM32L432KCU6). -My setup is 3 Wire SPI, S9 mode
I tried a lot and red many other issues taken by other people but did not get it working... Then i compared the "old" SPI clock from the arduino VS the new SPI and tweaked it, so the new looks the same now, but still nothing. (surprisingly the old SPI clock did not match the LCD specs(ec. SCK default low, 8 Bit ...). but still works. No clue why) Also the CS and RST line have the right level.
Here is my code: main.txt
You saw errors? Or need more detailed infos just say. Any help appreciated. Thanks in advance. Basti ;)