[Solved]ST7920 conversion from HAL to registers! - Page 1
Forum section: electronics / general

author: kgavionics
author_rank: Regular Contributor
timestamp: February 26, 2023, 06:58:00 pm
content: Hello guysI'm trying to convert the bellow library from HAL to registers and I did all the necessary steps in my opinion, but I can't make the display to work! Guys! please ignore all the advanced functions for drawing circles and lines and so on...all it matters to me now is to display a string!original code:Code:/** ST7920_SERIAL.c** Created on: 07-Jun-2019* Author: poe*/#include "stm32f1xx_hal.h"#include "ST7920_SERIAL.h"#include "delay.h"/* setup below is as follows* A5 ---------> SCLK (EN)* A6 ---------> CS (RS)* A7 ---------> SID (RW)* B0 ---------> RST (RST)**/#define SCLK_PIN GPIO_PIN_5#define SCLK_PORT GPIOA#define CS_PIN GPIO_PIN_6#define CS_PORT GPIOA#define SID_PIN GPIO_PIN_7#define SID_PORT GPIOA#define RST_PIN GPIO_PIN_0#define RST_PORT GPIOBuint8_t startRow, startCol, endRow, endCol; // coordinates of the dirty rectangleuint8_t numRows = 64;uint8_t numCols = 128;uint8_t Graphic_Check = 0;// A replacement for SPI_TRANSMITvoid SendByteSPI(uint8_t byte){for(int i=0;i<8;i++){if((byte<<i)&0x80){HAL_GPIO_WritePin(SID_PORT, SID_PIN, GPIO_PIN_SET); // SID=1 OR MOSI}else HAL_GPIO_WritePin(SID_PORT, SID_PIN, GPIO_PIN_RESET); // SID=0HAL_GPIO_WritePin(SCLK_PORT, SCLK_PIN, GPIO_PIN_RESET); // SCLK =0 OR SCKHAL_GPIO_WritePin(SCLK_PORT, SCLK_PIN, GPIO_PIN_SET); // SCLK=1}}void ST7920_SendCmd (uint8_t cmd){HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET); // PUll the CS highSendByteSPI(0xf8+(0<<1)); // send the SYNC + RS(0)SendByteSPI(cmd&0xf0); // send the higher nibble firstSendByteSPI((cmd<<4)&0xf0); // send the lower nibbledelay_us(50);HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET); // PUll the CS LOW}void ST7920_SendData (uint8_t data){HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET); // PUll the CS highSendByteSPI(0xf8+(1<<1)); // send the SYNC + RS(1)SendByteSPI(data&0xf0); // send the higher nibble firstSendByteSPI((data<<4)&0xf0); // send the lower nibbledelay_us(50);HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET); // PUll the CS LOW}void ST7920_SendString(int row, int col, char* string){switch (row){case 0:col |= 0x80;break;case 1:col |= 0x90;break;case 2:col |= 0x88;break;case 3:col |= 0x98;break;default:col |= 0x80;break;}ST7920_SendCmd(col);while (*string){ST7920_SendData(*string++);}}// switch to graphic mode or normal mode::: enable = 1 -> graphic mode enable = 0 -> normal modevoid ST7920_GraphicMode (int enable) // 1-enable, 0-disable{if (enable == 1){ST7920_SendCmd(0x30); // 8 bit modeHAL_Delay (1);ST7920_SendCmd(0x34); // switch to Extended instructionsHAL_Delay (1);ST7920_SendCmd(0x36); // enable graphicsHAL_Delay (1);Graphic_Check = 1; // update the variable}else if (enable == 0){ST7920_SendCmd(0x30); // 8 bit modeHAL_Delay (1);Graphic_Check = 0; // update the variable}}void ST7920_DrawBitmap(const unsigned char* graphic){uint8_t x, y;for(y = 0; y < 64; y++){if(y < 32){for(x = 0; x < 8; x++)// Draws top half of the screen.{// In extended instruction mode, vertical and horizontal coordinates must be specified before sending data in.ST7920_SendCmd(0x80 | y);// Vertical coordinate of the screen is specified first. (0-31)ST7920_SendCmd(0x80 | x);// Then horizontal coordinate of the screen is specified. (0-8)ST7920_SendData(graphic[2*x + 16*y]);// Data to the upper byte is sent to the coordinate.ST7920_SendData(graphic[2*x+1 + 16*y]);// Data to the lower byte is sent to the coordinate.}}else{for(x = 0; x < 8; x++)// Draws bottom half of the screen.{// Actions performed as same as the upper half screen.ST7920_SendCmd(0x80 | (y-32));// Vertical coordinate must be scaled back to 0-31 as it is dealing with another half of the screen.ST7920_SendCmd(0x88 | x);ST7920_SendData(graphic[2*x + 16*y]);ST7920_SendData(graphic[2*x+1 + 16*y]);}}}}// Update the display with the selected graphicsvoid ST7920_Update(void){ST7920_DrawBitmap(image);}void ST7920_Clear(){if (Graphic_Check == 1) // if the graphic mode is set{uint8_t x, y;for(y = 0; y < 64; y++){if(y < 32){ST7920_SendCmd(0x80 | y);ST7920_SendCmd(0x80);}else{ST7920_SendCmd(0x80 | (y-32));ST7920_SendCmd(0x88);}for(x = 0; x < 8; x++){ST7920_SendData(0);ST7920_SendData(0);}}}else{ST7920_SendCmd(0x01); // clear the display using commandHAL_Delay(2); // delay >1.6 ms}}void ST7920_Init (void){HAL_GPIO_WritePin(RST_PORT, RST_PIN, GPIO_PIN_RESET); // RESET=0HAL_Delay(10); // wait for 10msHAL_GPIO_WritePin(RST_PORT, RST_PIN, GPIO_PIN_SET); // RESET=1HAL_Delay(50); //wait for >40 msST7920_SendCmd(0x30); // 8bit modedelay_us(110); // >100us delayST7920_SendCmd(0x30); // 8bit modedelay_us(40); // >37us delayST7920_SendCmd(0x08); // D=0, C=0, B=0delay_us(110); // >100us delayST7920_SendCmd(0x01); // clear screenHAL_Delay(12); // >10 ms delayST7920_SendCmd(0x06); // cursor increment right no shiftHAL_Delay(1); // 1ms delayST7920_SendCmd(0x0C); // D=1, C=0, B=0HAL_Delay(1); // 1ms delayST7920_SendCmd(0x02); // return to homeHAL_Delay(1); // 1ms delay}// set Pixelvoid SetPixel(uint8_t x, uint8_t y){if (y < numRows && x < numCols){uint8_t *p = image + ((y * (numCols/8)) + (x/8));*p |= 0x80u >> (x%8);*image = *p;// Change the dirty rectangle to account for a pixel being dirty (we assume it was changed)if (startRow > y) { startRow = y; }if (endRow <= y) { endRow = y + 1; }if (startCol > x) { startCol = x; }if (endCol <= x) { endCol = x + 1; }}}/* draw a line* start point (X0, Y0)* end point (X1, Y1)*/void DrawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1){int dx = (x1 >= x0) ? x1 - x0 : x0 - x1;int dy = (y1 >= y0) ? y1 - y0 : y0 - y1;int sx = (x0 < x1) ? 1 : -1;int sy = (y0 < y1) ? 1 : -1;int err = dx - dy;for (;;){SetPixel(x0, y0);if (x0 == x1 && y0 == y1) break;int e2 = err + err;if (e2 > -dy){err -= dy;x0 += sx;}if (e2 < dx){err += dx;y0 += sy;}}}/* Draw rectangle* start point (x,y)* w -> width* h -> height*/void DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h){/* Check input parameters */if (x >= numCols ||y >= numRows) {/* Return error */return;}/* Check width and height */if ((x + w) >= numCols) {w = numCols - x;}if ((y + h) >= numRows) {h = numRows - y;}/* Draw 4 lines */DrawLine(x, y, x + w, y); /* Top line */DrawLine(x, y + h, x + w, y + h); /* Bottom line */DrawLine(x, y, x, y + h); /* Left line */DrawLine(x + w, y, x + w, y + h); /* Right line */}/* Draw filled rectangle* Start point (x,y)* w -> width* h -> height*/void DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h){uint8_t i;/* Check input parameters */if (x >= numCols ||y >= numRows) {/* Return error */return;}/* Check width and height */if ((x + w) >= numCols) {w = numCols - x;}if ((y + h) >= numRows) {h = numRows - y;}/* Draw lines */for (i = 0; i <= h; i++) {/* Draw lines */DrawLine(x, y + i, x + w, y + i);}}/* draw circle* centre (x0,y0)* radius = radius*/void DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius){int f = 1 - (int)radius;int ddF_x = 1;int ddF_y = -2 * (int)radius;int x = 0;SetPixel(x0, y0 + radius);SetPixel(x0, y0 - radius);SetPixel(x0 + radius, y0);SetPixel(x0 - radius, y0);int y = radius;while(x < y){if(f >= 0){y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;SetPixel(x0 + x, y0 + y);SetPixel(x0 - x, y0 + y);SetPixel(x0 + x, y0 - y);SetPixel(x0 - x, y0 - y);SetPixel(x0 + y, y0 + x);SetPixel(x0 - y, y0 + x);SetPixel(x0 + y, y0 - x);SetPixel(x0 - y, y0 - x);}}// Draw Filled Circlevoid DrawFilledCircle(int16_t x0, int16_t y0, int16_t r){int16_t f = 1 - r;int16_t ddF_x = 1;int16_t ddF_y = -2 * r;int16_t x = 0;int16_t y = r;SetPixel(x0, y0 + r);SetPixel(x0, y0 - r);SetPixel(x0 + r, y0);SetPixel(x0 - r, y0);DrawLine(x0 - r, y0, x0 + r, y0);while (x < y) {if (f >= 0) {y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;DrawLine(x0 - x, y0 + y, x0 + x, y0 + y);DrawLine(x0 + x, y0 - y, x0 - x, y0 - y);DrawLine(x0 + y, y0 + x, x0 - y, y0 + x);DrawLine(x0 + y, y0 - x, x0 - y, y0 - x);}}// Draw Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)void DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){/* Draw lines */DrawLine(x1, y1, x2, y2);DrawLine(x2, y2, x3, y3);DrawLine(x3, y3, x1, y1);}// Draw Filled Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)void DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,curpixel = 0;#define ABS(x) ((x) > 0 ? (x) : -(x))deltax = ABS(x2 - x1);deltay = ABS(y2 - y1);x = x1;y = y1;if (x2 >= x1) {xinc1 = 1;xinc2 = 1;} else {xinc1 = -1;xinc2 = -1;}if (y2 >= y1) {yinc1 = 1;yinc2 = 1;} else {yinc1 = -1;yinc2 = -1;}if (deltax >= deltay){xinc1 = 0;yinc2 = 0;den = deltax;num = deltax / 2;numadd = deltay;numpixels = deltax;} else {xinc2 = 0;yinc1 = 0;den = deltay;num = deltay / 2;numadd = deltax;numpixels = deltay;}for (curpixel = 0; curpixel <= numpixels; curpixel++){DrawLine(x, y, x3, y3);num += numadd;if (num >= den) {num -= den;x += xinc1;y += yinc1;}x += xinc2;y += yinc2;}}my codeCode:#include<stm32f407xx.h>#include<stdint.h>#include"functions.h"uint8_t image[(128 * 64)/8];/* setup below is as follows* PA0 ---------> SCLK (EN) 1* PA1---------> MOSI (RW) 2* PA2 ---------> CS (RS) 3* PA3 ---------> RST (RST) 4**/#define GLCD_SLK0#define _GLCD_SLK16#define GLCD_MOSI 1#define _GLCD_MOSI 17#define GLCD_CS2#define _GLCD_CS18#define GLCD_RESET3#define _GLCD_RESET19uint8_t startRow, startCol, endRow, endCol; // coordinates of the dirty rectangleuint8_t numRows = 64;uint8_t numCols = 128;uint8_t Graphic_Check = 0;void SendByteSPI(uint8_t byte){for(int i=0;i<8;i++){if((byte<<i)&0x80){GPIOA->BSRR =(1<< GLCD_MOSI); //MOSI=1}elseGPIOA->BSRR =(1<< _GLCD_MOSI); //MOSI=0GPIOA->BSRR =(1<< _GLCD_SLK); //SLK=0GPIOA->BSRR =(1<< GLCD_SLK); //SLK=1}}void ST7920_SendCmd (uint8_t cmd){// PUll the CS highGPIOA->BSRR = (1 << GLCD_CS);SendByteSPI(0xf8+(0<<1)); // send the SYNC + RS(0)SendByteSPI(cmd&0xf0); // send the higher nibble firstSendByteSPI((cmd<<4)&0xf0); // send the lower nibbleDelay_us(50);// PUll the CS LOWGPIOA->BSRR = (1 << _GLCD_CS);}void ST7920_SendData (uint8_t data){GPIOA->BSRR = (1 << GLCD_CS); // PUll the CS highSendByteSPI(0xf8+(1<<1)); // send the SYNC + RS(1)SendByteSPI(data&0xf0); // send the higher nibble firstSendByteSPI((data<<4)&0xf0); // send the lower nibbleDelay_us(50);GPIOA->BSRR = (1 << _GLCD_CS); // PUll the CS LOW}void ST7920_SendString(int row, int col, char* string){switch (row){case 0:col |= 0x80;break;case 1:col |= 0x90;break;case 2:col |= 0x88;break;case 3:col |= 0x98;break;default:col |= 0x80;break;}ST7920_SendCmd(col);while (*string){ST7920_SendData(*string++);}}// switch to graphic mode or normal mode::: enable = 1 -> graphic mode enable = 0 -> normal modevoid ST7920_GraphicMode (int enable) // 1-enable, 0-disable{if (enable == 1){ST7920_SendCmd(0x30); // 8 bit modeDelay_ms (1);ST7920_SendCmd(0x34); // switch to Extended instructionsDelay_ms (1);ST7920_SendCmd(0x36); // enable graphicsDelay_ms (1);Graphic_Check = 1; // update the variable}else if (enable == 0){ST7920_SendCmd(0x30); // 8 bit modeDelay_ms (1);Graphic_Check = 0; // update the variable}}void ST7920_DrawBitmap(const unsigned char* graphic){uint8_t x, y;for(y = 0; y < 64; y++){if(y < 32){for(x = 0; x < 8; x++)// Draws top half of the screen.{// In extended instruction mode, vertical and horizontal coordinates must be specified before sending data in.ST7920_SendCmd(0x80 | y);// Vertical coordinate of the screen is specified first. (0-31)ST7920_SendCmd(0x80 | x);// Then horizontal coordinate of the screen is specified. (0-8)ST7920_SendData(graphic[2*x + 16*y]);// Data to the upper byte is sent to the coordinate.ST7920_SendData(graphic[2*x+1 + 16*y]);// Data to the lower byte is sent to the coordinate.}}else{for(x = 0; x < 8; x++)// Draws bottom half of the screen.{// Actions performed as same as the upper half screen.ST7920_SendCmd(0x80 | (y-32));// Vertical coordinate must be scaled back to 0-31 as it is dealing with another half of the screen.ST7920_SendCmd(0x88 | x);ST7920_SendData(graphic[2*x + 16*y]);ST7920_SendData(graphic[2*x+1 + 16*y]);}}}}// Update the display with the selected graphicsvoid ST7920_Update(void){//ST7920_DrawBitmap(image);}void ST7920_Clear(){if (Graphic_Check == 1) // if the graphic mode is set{uint8_t x, y;for(y = 0; y < 64; y++){if(y < 32){ST7920_SendCmd(0x80 | y);ST7920_SendCmd(0x80);}else{ST7920_SendCmd(0x80 | (y-32));ST7920_SendCmd(0x88);}for(x = 0; x < 8; x++){ST7920_SendData(0);ST7920_SendData(0);}}}else{ST7920_SendCmd(0x01); // clear the display using commandDelay_ms(2); // delay >1.6 ms}}void ST7920_Init (void){GPIOA->BSRR = (1<< _GLCD_RESET); // RESET=0Delay_ms(10); // wait for 10msGPIOA->BSRR = (1<< GLCD_RESET); // RESET=1Delay_ms(50); //wait for >40 msST7920_SendCmd(0x30); // 8bit modeDelay_us(110); // >100us delayST7920_SendCmd(0x30); // 8bit modeDelay_us(40); // >37us delayST7920_SendCmd(0x08); // D=0, C=0, B=0Delay_us(110); // >100us delayST7920_SendCmd(0x01); // clear screenDelay_ms(12); // >10 ms delayST7920_SendCmd(0x06); // cursor increment right no shiftDelay_ms(1); // 1ms delayST7920_SendCmd(0x0C); // D=1, C=0, B=0Delay_ms(1); // 1ms delayST7920_SendCmd(0x02); // return to homeDelay_ms(1); // 1ms delay}// set Pixelvoid SetPixel(uint8_t x, uint8_t y){if (y < numRows && x < numCols){uint8_t *p = image + ((y * (numCols/8)) + (x/8));*p |= 0x80u >> (x%8);*image = *p;// Change the dirty rectangle to account for a pixel being dirty (we assume it was changed)if (startRow > y) { startRow = y; }if (endRow <= y) { endRow = y + 1; }if (startCol > x) { startCol = x; }if (endCol <= x) { endCol = x + 1; }}}/* draw a line* start point (X0, Y0)* end point (X1, Y1)*/void DrawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1){int dx = (x1 >= x0) ? x1 - x0 : x0 - x1;int dy = (y1 >= y0) ? y1 - y0 : y0 - y1;int sx = (x0 < x1) ? 1 : -1;int sy = (y0 < y1) ? 1 : -1;int err = dx - dy;for (;;){SetPixel(x0, y0);if (x0 == x1 && y0 == y1) break;int e2 = err + err;if (e2 > -dy){err -= dy;x0 += sx;}if (e2 < dx){err += dx;y0 += sy;}}}/* Draw rectangle* start point (x,y)* w -> width* h -> height*/void DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h){/* Check input parameters */if (x >= numCols ||y >= numRows) {/* Return error */return;}/* Check width and height */if ((x + w) >= numCols) {w = numCols - x;}if ((y + h) >= numRows) {h = numRows - y;}/* Draw 4 lines */DrawLine(x, y, x + w, y); /* Top line */DrawLine(x, y + h, x + w, y + h); /* Bottom line */DrawLine(x, y, x, y + h); /* Left line */DrawLine(x + w, y, x + w, y + h); /* Right line */}/* Draw filled rectangle* Start point (x,y)* w -> width* h -> height*/void DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h){uint8_t i;/* Check input parameters */if (x >= numCols ||y >= numRows) {/* Return error */return;}/* Check width and height */if ((x + w) >= numCols) {w = numCols - x;}if ((y + h) >= numRows) {h = numRows - y;}/* Draw lines */for (i = 0; i <= h; i++) {/* Draw lines */DrawLine(x, y + i, x + w, y + i);}}/* draw circle* centre (x0,y0)* radius = radius*/void DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius){int f = 1 - (int)radius;int ddF_x = 1;int ddF_y = -2 * (int)radius;int x = 0;SetPixel(x0, y0 + radius);SetPixel(x0, y0 - radius);SetPixel(x0 + radius, y0);SetPixel(x0 - radius, y0);int y = radius;while(x < y){if(f >= 0){y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;SetPixel(x0 + x, y0 + y);SetPixel(x0 - x, y0 + y);SetPixel(x0 + x, y0 - y);SetPixel(x0 - x, y0 - y);SetPixel(x0 + y, y0 + x);SetPixel(x0 - y, y0 + x);SetPixel(x0 + y, y0 - x);SetPixel(x0 - y, y0 - x);}}// Draw Filled Circlevoid DrawFilledCircle(int16_t x0, int16_t y0, int16_t r){int16_t f = 1 - r;int16_t ddF_x = 1;int16_t ddF_y = -2 * r;int16_t x = 0;int16_t y = r;SetPixel(x0, y0 + r);SetPixel(x0, y0 - r);SetPixel(x0 + r, y0);SetPixel(x0 - r, y0);DrawLine(x0 - r, y0, x0 + r, y0);while (x < y) {if (f >= 0) {y--;ddF_y += 2;f += ddF_y;}x++;ddF_x += 2;f += ddF_x;DrawLine(x0 - x, y0 + y, x0 + x, y0 + y);DrawLine(x0 + x, y0 - y, x0 - x, y0 - y);DrawLine(x0 + y, y0 + x, x0 - y, y0 + x);DrawLine(x0 + y, y0 - x, x0 - y, y0 - x);}}// Draw Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)void DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){/* Draw lines */DrawLine(x1, y1, x2, y2);DrawLine(x2, y2, x3, y3);DrawLine(x3, y3, x1, y1);}// Draw Filled Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)void DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,curpixel = 0;#define ABS(x) ((x) > 0 ? (x) : -(x))deltax = ABS(x2 - x1);deltay = ABS(y2 - y1);x = x1;y = y1;if (x2 >= x1) {xinc1 = 1;xinc2 = 1;} else {xinc1 = -1;xinc2 = -1;}if (y2 >= y1) {yinc1 = 1;yinc2 = 1;} else {yinc1 = -1;yinc2 = -1;}if (deltax >= deltay){xinc1 = 0;yinc2 = 0;den = deltax;num = deltax / 2;numadd = deltay;numpixels = deltax;} else {xinc2 = 0;yinc1 = 0;den = deltay;num = deltay / 2;numadd = deltax;numpixels = deltay;}for (curpixel = 0; curpixel <= numpixels; curpixel++){DrawLine(x, y, x3, y3);num += numadd;if (num >= den) {num -= den;x += xinc1;y += yinc1;}x += xinc2;y += yinc2;}}gpio_init ()Code:RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;GPIOA->MODER |= 1U<<0 | 1U<<2 | 1U<<4 | 1U<<6; //PA0-PA3 OUTPUT FOR ST7920my mainCode:#include<stm32f407xx.h>#include"ST7920_SERIAL.h"#include"functions.h"#include "bitmap.h"int main(void){SysClockConfig();gpio_init();ST7920_Init();ST7920_SendString(0,0, "HELLO WORLD");while(1);}For who may ask about the delay routine, I made sure they are tested and working, so they're not the culprit!Can someone help me please, because I can't see why this display is not working with my stm32f407 board ( display is fully working with arduino).Thank you in advance!

author: wek
author_rank: Frequent Contributor
timestamp: February 27, 2023, 08:27:43 am
content: Observe/compare waveforms on pins, check datasheet.ThisCode:void SendByteSPI(uint8_t byte){for(int i=0;i<8;i++){if((byte<<i)&0x80){GPIOA->BSRR =(1<< GLCD_MOSI); //MOSI=1}elseGPIOA->BSRR =(1<< _GLCD_MOSI); //MOSI=0GPIOA->BSRR =(1<< _GLCD_SLK); //SLK=0GPIOA->BSRR =(1<< GLCD_SLK); //SLK=1}}may simply be too fast for the display, or maybe even the GPIO pins, depending on how you've set them and depending on the particular clock setup.Why don't you use the SPI module?JW

author: Siwastaja
author_rank: Super Contributor
timestamp: February 27, 2023, 09:41:33 am
content: +1 for wek's suggestion: capture signals on oscillosscope using the original code, then run your modified code and look for differences.

author: wek
author_rank: Frequent Contributor
timestamp: February 27, 2023, 10:09:16 am
content: Quote from: Siwastaja on February 27, 2023, 09:41:33 amRe-reading the original post, it appears that the code which was presented as the original (with Cube/HAL) was probably never tested on the target hardware, as the port pins are different, andQuote from: kgavionics in original postJW

author: Siwastaja
author_rank: Super Contributor
timestamp: February 27, 2023, 10:16:09 am
content: Yes. The strategy which always works, whether writing new code or modifying old one, is just to look the signals on scope (or logic analyzer) and compare to the display datasheet timing diagrams and description, until an error is found.If you write code "blindly", chances are high some signals are completely missing, for example wrong pin configuration or even a short-circuit on the prototype.

author: tellurium
author_rank: Frequent Contributor
timestamp: February 27, 2023, 11:13:33 am
content: My suggestion would be to write your own "hal.h", with your own higher level functions based on CMSIS definitions. Don't hardcode numbers / offsets , it'll be a nightmare to maintain. If you hardcode, you'll forget their meaning next week.See example for STM32F4 (the GPIO / UART API will most definitely work on your 407):Custom hal.h for F4, GPIO API:https://github.com/cesanta/mongoose/blob/67dea15bf21df5106f9959eb87405be14f7760ac/examples/stm32/nucleo-f429zi-baremetal/hal.h#L34-L72This code you will understand at any time in the future, and it'll be very easy to maintain or port it:Code:uint16_t led = PIN('B', 7);gpio_output(led);gpio_write(led, 1);Or, more elaborate:https://github.com/cesanta/mongoose/blob/67dea15bf21df5106f9959eb87405be14f7760ac/examples/stm32/nucleo-f429zi-baremetal/main.c#L42-L48

author: kgavionics
author_rank: Regular Contributor
timestamp: February 27, 2023, 02:05:48 pm
content: Thank you guys for all your input!Before I used the bit banging SPI, I used the Hardware SPI function below, but it didn't work, so I decided to use the software SPI.Code:uint8_t SendByteSPI(uint8_t byte){GPIOB->BSRR = (1 << _GLCD_CS);SPI2->DR = byte;/* send the contents of d */while((SPI2->SR&(1<<0)) == 0);/* wait until RXNE is set */GPIOB->BSRR = (1 << GLCD_CS);return SPI2->DR;/* return the received data */}I'll try to use my oscilloscope to check the signals and report back!Update: problem fixed by introducing a small delay in the SendByteSPI function. My MCU is running at 168 MHZ, so my GPIO ports! As a result, the display couldn't keep up with my MCU!Thank you guys for your help!