I’m trying to port Adafruit_TFTLCD library (for 8bit parallel LCD) and inside in library, control lines is controlled by macros, using port manipulation, but STM32 has a different method to make this. Using AVR, library make control using DDRA and PORTA, for example, to control port direction and values. How can I make this manipulations? Using GPIOA_BASE.CRL, GPIOA_BASE.CRH, GPIOA_BASE.IDR and GPIOA_BASE.ODR?
Follow a piece of code in pin_magic.h:
#define write8inline(d) { \
PORTD = (PORTD & B00000011) | ((d) & B11111100); \
PORTB = (PORTB & B11111100) | ((d) & B00000011); \
WR_STROBE; }
#define read8inline(result) { \
RD_ACTIVE; \
DELAY7; \
result = (PIND & B11111100) | (PINB & B00000011); \
RD_IDLE; }
#define setWriteDirInline() { DDRD |= B11111100; DDRB |= B00000011; }
#define setReadDirInline() { DDRD &= ~B11111100; DDRB &= ~B00000011; }
Each port has multiple registers, but I think the ones you are interested in is the Output Data Register (ODR) (Not there are also a separate high speed register to Set bits, Reset bits)
If you look in system/libmaple/include/libmaple/gpio.h there is a function to toggle a single bit
static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) {
dev->regs->ODR = dev->regs->ODR ^ (1U << pin);
}
So if you do
dev->regs->ODR = 0x1234
it will set whichever port to 0x1234
Note the ports are 16 bits wide, so you will need to read / mask / write to just update just 8 bits, so thinking about it, it may actually be quicker to write to the BSSR register, e.g. something like
dev->regs->BSRR = (youNum & 0x0F) | ~(yourNum & 0x0F)<<16;
You’d need to double check this code, but I think you’ll probably get the idea.
The device “dev->” have defines in the code already
GPIOA, GPIOB, GPIOC etc etc
Anyway, that should give you a head start ..
Anyway, that should give you a head start ..
Note the ports are 16 bits wide, so you will need to read / mask / write to just update just 8 bits, so thinking about it, it may actually be quicker to write to the BSSR register, e.g. something like
dev->regs->BSRR = (youNum & 0x0F) | ~(yourNum & 0x0F)<<16;
<…>
my braincell is overloaded and it’s been a long night/day, but where do the 0x0f masks and the << 16 come from?
0xff’s and << 8 are what i’d expect?
stephen
In pin_magic.h:
#elif defined(__STM32F1__)
// Data pins is PA4 PA5 PA6 PA7 - PB12 PB13 PB14 PB15
#define write8inline(d) { \
GPIOA->regs->ODR = ((GPIOA->regs->ODR & 0xFF0F) | ((d << 4) & 0x00F0)); \
GPIOB->regs->ODR = ((GPIOB->regs->ODR & 0x0FFF) | ((d << 8) & 0xF000)); \
WR_STROBE; }
#define read8inline(result) { \
RD_ACTIVE; \
delayMicroseconds(1); \
result = (((GPIOA->regs->IDR & 0x00F0) >> 4) | ((GPIOB->regs->IDR & 0xF000) >> 8)); \
RD_IDLE;}
#define setWriteDirInline() { \
GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x33330000); \
GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x33330000); \
}
#define setReadDirInline() { \
GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x44440000); \
GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x44440000); \
}
// When using the TFT breakout board, control pins are configurable.
#define RD_ACTIVE rdPort->regs->BRR |= rdPinSet //PIO_Clear(rdPort, rdPinSet)
#define RD_IDLE rdPort->regs->BSRR |= rdPinSet //PIO_Set(rdPort, rdPinSet)
#define WR_ACTIVE wrPort->regs->BRR |= wrPinSet //PIO_Clear(wrPort, wrPinSet)
#define WR_IDLE wrPort->regs->BSRR |= wrPinSet //PIO_Set(wrPort, wrPinSet)
#define CD_COMMAND cdPort->regs->BRR |= cdPinSet //PIO_Clear(cdPort, cdPinSet)
#define CD_DATA cdPort->regs->BSRR |= cdPinSet //PIO_Set(cdPort, cdPinSet)
#define CS_ACTIVE csPort->regs->BRR |= csPinSet //PIO_Clear(csPort, csPinSet)
#define CS_IDLE csPort->regs->BSRR |= csPinSet //PIO_Set(csPort, csPinSet)
// As part of the inline control, macros reference other macros...if any
// of these are left undefined, an equivalent function version (non-inline)
// is declared later. The Uno has a moderate amount of program space, so
// only write8() is inlined -- that one provides the most performance
// benefit, but unfortunately also generates the most bloat. This is
// why only certain cases are inlined for each board.
#define write8 write8inline
#else
If it’s the backlight than connect it to VCC, the STM32 cannot give enough power for driving the backlight for the LCD via a single pin without additional hardware.
If it’s the backlight than connect it to VCC, the STM32 cannot give enough power for driving the backlight for the LCD via a single pin without additional hardware.
This is likely to cause problems, because the STM32 is a 3.3V device not 5V device.
I recommend you power the LCD from 3.3V
This is likely to cause problems, because the STM32 is a 3.3V device not 5V device.
I recommend you power the LCD from 3.3V
// Data pins is PA4 PA5 PA6 PA7 - PB12 PB13 PB14 PB15
#define write8inline(d) { \
GPIOA->regs->BRR = ((GPIOA->regs->BRR & 0xFF0F) | ((d << 4) & 0x00F0)); \
GPIOA->regs->BSRR = ((GPIOA->regs->BSRR & 0xFF0F) | ((~d << 4) & 0x00F0)); \
GPIOB->regs->BRR = ((GPIOB->regs->BRR & 0x0FFF) | ((d << 8) & 0xF000)); \
GPIOB->regs->BSRR = ((GPIOB->regs->BSRR & 0x0FFF) | ((~d << 8) & 0xF000)); \
WR_STROBE; }
void write8(uint8_t value)
{
write8inline(value);
}
In pin_magic.h:
#elif defined(__STM32F1__)
// Data pins is PA4 PA5 PA6 PA7 - PB12 PB13 PB14 PB15
#define write8inline(d) { \
GPIOA->regs->ODR = ((GPIOA->regs->ODR & 0xFF0F) | ((d << 4) & 0x00F0)); \
GPIOB->regs->ODR = ((GPIOB->regs->ODR & 0x0FFF) | ((d << 8) & 0xF000)); \
WR_STROBE; }
#define read8inline(result) { \
RD_ACTIVE; \
delayMicroseconds(1); \
result = (((GPIOA->regs->IDR & 0x00F0) >> 4) | ((GPIOB->regs->IDR & 0xF000) >> 8)); \
RD_IDLE;}
#define setWriteDirInline() { \
GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x33330000); \
GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x33330000); \
}
#define setReadDirInline() { \
GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x44440000); \
GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x44440000); \
}
// When using the TFT breakout board, control pins are configurable.
#define RD_ACTIVE rdPort->regs->BRR |= rdPinSet //PIO_Clear(rdPort, rdPinSet)
#define RD_IDLE rdPort->regs->BSRR |= rdPinSet //PIO_Set(rdPort, rdPinSet)
#define WR_ACTIVE wrPort->regs->BRR |= wrPinSet //PIO_Clear(wrPort, wrPinSet)
#define WR_IDLE wrPort->regs->BSRR |= wrPinSet //PIO_Set(wrPort, wrPinSet)
#define CD_COMMAND cdPort->regs->BRR |= cdPinSet //PIO_Clear(cdPort, cdPinSet)
#define CD_DATA cdPort->regs->BSRR |= cdPinSet //PIO_Set(cdPort, cdPinSet)
#define CS_ACTIVE csPort->regs->BRR |= csPinSet //PIO_Clear(csPort, csPinSet)
#define CS_IDLE csPort->regs->BSRR |= csPinSet //PIO_Set(csPort, csPinSet)
// As part of the inline control, macros reference other macros...if any
// of these are left undefined, an equivalent function version (non-inline)
// is declared later. The Uno has a moderate amount of program space, so
// only write8() is inlined -- that one provides the most performance
// benefit, but unfortunately also generates the most bloat. This is
// why only certain cases are inlined for each board.
#define write8 write8inline
#else
Here’s an example to start ili9341.
/********************************************************************/
#include "stm32f10x_gpio.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
/*******************************************************************/
#define LCD_DATA ((uint32_t)0x60020000)
#define LCD_REG ((uint32_t)0x60000000)
/*******************************************************************/
void delay(uint32_t delayTime)
{
uint32_t i;
for(i = 0; i < delayTime; i++);
}
/*******************************************************************/
/*void writeLCDCommand(unsigned int reg,unsigned int value)
{
*(uint16_t *) (LCD_REG) = reg;
*(uint16_t *) (LCD_DATA) = value;
}*/
/*******************************************************************/
void LCD_Write_COM(unsigned int reg)
{
*(uint16_t *) (LCD_REG) = reg;
//*(uint16_t *) (LCD_DATA) = value;
}
/*******************************************************************/
//void writeLCDData(unsigned int data)
void LCD_Write_DATA(unsigned int data)
{
*(uint16_t *) (LCD_DATA)= data;
}
/*******************************************************************/
void Lcd_data_start(void)
{
LCD_Write_COM(0x2c);
}
/*******************************************************************/
void Global_reset(void)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
delay(0x0FFFFF);
GPIO_SetBits(GPIOE, GPIO_Pin_1 );
delay(0x0FFFFF);
}
/*******************************************************************/
void initAll()
{
FSMC_NORSRAMInitTypeDef fsmc;
FSMC_NORSRAMTimingInitTypeDef fsmcTiming;
GPIO_InitTypeDef gpio;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &gpio);
gpio.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &gpio);
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &gpio);
// Здесь у нас Reset
gpio.GPIO_Pin = GPIO_Pin_1 ;
GPIO_Init(GPIOE, &gpio);
// CS
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOD, &gpio);
// RS
gpio.GPIO_Pin = GPIO_Pin_11 ;
GPIO_Init(GPIOD, &gpio);
// CS -> 1
// Reset -> 0
// RD -> 1
// RW -> 1
GPIO_SetBits(GPIOD, GPIO_Pin_7);
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
fsmcTiming.FSMC_AddressSetupTime = 0x02;
fsmcTiming.FSMC_AddressHoldTime = 0x00;
fsmcTiming.FSMC_DataSetupTime = 0x05;
fsmcTiming.FSMC_BusTurnAroundDuration = 0x00;
fsmcTiming.FSMC_CLKDivision = 0x00;
fsmcTiming.FSMC_DataLatency = 0x00;
fsmcTiming.FSMC_AccessMode = FSMC_AccessMode_B;
fsmc.FSMC_Bank = FSMC_Bank1_NORSRAM1;
fsmc.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
fsmc.FSMC_MemoryType = FSMC_MemoryType_NOR;
fsmc.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
fsmc.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
fsmc.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
fsmc.FSMC_WrapMode = FSMC_WrapMode_Disable;
fsmc.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
fsmc.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
fsmc.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
fsmc.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
fsmc.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
fsmc.FSMC_ReadWriteTimingStruct = &fsmcTiming;
fsmc.FSMC_WriteTimingStruct = &fsmcTiming;
fsmc.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInit(&fsmc);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}
/*******************************************************************/
void initLCD()
{
Global_reset();
LCD_Write_COM(0x01); //reset
delay(15);
LCD_Write_COM(0x11);//sleep out
delay(20);
LCD_Write_COM(0x28); //display off
delay(5);
LCD_Write_COM(0xCF); //power control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0xC1); //83 81 AA
LCD_Write_DATA(0x30);
LCD_Write_COM(0xED); //power on seq control
LCD_Write_DATA(0x64); //64 67
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x12);
LCD_Write_DATA(0x81);
LCD_Write_COM(0xE8); //timing control a
LCD_Write_DATA(0x85);
LCD_Write_DATA(0x00); // 01
LCD_Write_DATA(0x78); //79 78
LCD_Write_COM(0xCB); //power control a
LCD_Write_DATA(0x39);
LCD_Write_DATA(0X2C);
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x34);
LCD_Write_DATA(0x02);
LCD_Write_COM(0xF7); //pump ratio control
LCD_Write_DATA(0x20);
LCD_Write_COM(0xEA); //timing control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xC0); //power control 2
LCD_Write_DATA(0x23); //26 25
LCD_Write_COM(0xC1); //power control 2
LCD_Write_DATA(0x10);// 11
LCD_Write_COM(0xC5); //vcom control 1
LCD_Write_DATA(0x3E);// 35
LCD_Write_DATA(0x28);// 3E
LCD_Write_COM(0xC7); //vcom control 2
LCD_Write_DATA(0x86); //BE 94
LCD_Write_COM(0xB1); //frame control
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x18); //1B 70
LCD_Write_COM(0xB6); //display control
LCD_Write_DATA(0x08);// 0A
LCD_Write_DATA(0x82);
LCD_Write_DATA(0x27);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xB7); //emtry mode
LCD_Write_DATA(0x07);
LCD_Write_COM(0x3A); //pixel format
LCD_Write_DATA(0x55); //16bit
LCD_Write_COM(0xE0);
LCD_Write_DATA(0x0F);
LCD_Write_DATA(0x31);
LCD_Write_DATA(0x2B);
LCD_Write_DATA(0x0C);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x08);
LCD_Write_DATA(0x4E);
LCD_Write_DATA(0xF1);
LCD_Write_DATA(0x37);
LCD_Write_DATA(0x07);
LCD_Write_DATA(0x10);
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x09);
LCD_Write_DATA(0x00);
LCD_Write_COM(0x36); //mem access
//LCD_Write_DATA((1<<3)|(1<<6));
LCD_Write_DATA((1<<3)|(1<<7)); //rotate 180
LCD_Write_COM(0x29); //display on
LCD_Write_COM(0x2C);
delay(5);
/*writeLCDCommand(0x0015,0x0030);
writeLCDCommand(0x0011,0x0040);
writeLCDCommand(0x0010,0x1628);
writeLCDCommand(0x0012,0x0000);
writeLCDCommand(0x0013,0x104d);
delay(10);
writeLCDCommand(0x0012,0x0010);
delay(10);
writeLCDCommand(0x0010,0x2620);
writeLCDCommand(0x0013,0x344d);
delay(10);
writeLCDCommand(0x0001,0x0100);
writeLCDCommand(0x0002,0x0300);
writeLCDCommand(0x0003,0x1030);
writeLCDCommand(0x0008,0x0604);
writeLCDCommand(0x0009,0x0000);
writeLCDCommand(0x000A,0x0008);
writeLCDCommand(0x0041,0x0002);
writeLCDCommand(0x0060,0x2700);
writeLCDCommand(0x0061,0x0001);
writeLCDCommand(0x0090,0x0182);
writeLCDCommand(0x0093,0x0001);
writeLCDCommand(0x00a3,0x0010);
delay(10);
writeLCDCommand(0x30,0x0000);
writeLCDCommand(0x31,0x0502);
writeLCDCommand(0x32,0x0307);
writeLCDCommand(0x33,0x0305);
writeLCDCommand(0x34,0x0004);
writeLCDCommand(0x35,0x0402);
writeLCDCommand(0x36,0x0707);
writeLCDCommand(0x37,0x0503);
writeLCDCommand(0x38,0x1505);
writeLCDCommand(0x39,0x1505);
delay(10);
writeLCDCommand(0x0007,0x0001);
delay(10);
writeLCDCommand(0x0007,0x0021);
writeLCDCommand(0x0007,0x0023);
delay(10);
writeLCDCommand(0x0007,0x0033);
delay(10);
writeLCDCommand(0x0007,0x0133);*/
}
/*******************************************************************/
int main()
{
initAll();
delay(100);
initLCD();
while(1)
{
int i;
/*writeLCDCommand(0x0050, 0);
writeLCDCommand(0x0051, 239);
writeLCDCommand(0x0052, 0);
writeLCDCommand(0x0053, 319);
writeLCDCommand(32, 0);
writeLCDCommand(33, 0);*/
LCD_Write_COM(0x51);
LCD_Write_DATA(0x00);
*(uint16_t *) (LCD_REG) = 0x2C;
for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xF800);
}
delay(0xFFFFFF);
for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x07E0);
}
delay(0xFFFFFF);
for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x001F);
}
delay(0xFFFFFF);
for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x03EF);
}
delay(0xFFFFFF);
for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xFFE0);
}
delay(0xFFFFFF);
}
}
/*******************************************************************/
/*******************************************************************/
#include "stm32f10x_gpio.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include "reg_9341.h"
#define DELAY_TIME 1
#define TFTWIDTH 240
#define TFTHEIGHT 320
uint8_t rotation;
const uint16_t
WIDTH, HEIGHT;
uint16_t _width, _height;
/*******************************************************************/
// Определяем адреса, по которым будем записывать данные
// Для записи данных
#define LCD_DATA ((uint32_t)0x60020000)
// Для записи команд
#define LCD_REG ((uint32_t)0x60000000)
/*******************************************************************/
// Простенькая функция задержки
void delay(uint32_t delayTime)
{
uint32_t i;
for(i = 0; i < delayTime; i++);
}
/*******************************************************************/
// Так мы будем писать команды в регистры LCD
/*void writeLCDCommand(unsigned int reg,unsigned int value)
{
*(uint16_t *) (LCD_REG) = reg;
*(uint16_t *) (LCD_DATA) = value;
}*/
/*******************************************************************/// Так мы будем писать команды в регистры LCD
void LCD_Write_COM(unsigned int reg)
{
*(uint16_t *) (LCD_REG) = reg;
//*(uint16_t *) (LCD_DATA) = value;
}
/*******************************************************************/
// А так данные..
//void writeLCDData(unsigned int data)
void LCD_Write_DATA(unsigned int data)
{
*(uint16_t *) (LCD_DATA)= data;
}
/*******************************************************************/
void Lcd_data_start(void)
{
LCD_Write_COM(0x2c);
}
/*******************************************************************/
void Global_reset(void)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
delay(0x0FFFFF);
GPIO_SetBits(GPIOE, GPIO_Pin_1 );
delay(0x0FFFFF);
}
/*******************************************************************/
void initAll()
{
FSMC_NORSRAMInitTypeDef fsmc;
FSMC_NORSRAMTimingInitTypeDef fsmcTiming;
GPIO_InitTypeDef gpio;
// Включаем тактирование портов
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
// И тактирование FSMC
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
// Инициализация пинов, задейстованных в общении по FSMC
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &gpio);
gpio.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &gpio);
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &gpio);
// Здесь у нас Reset
gpio.GPIO_Pin = GPIO_Pin_1 ;
GPIO_Init(GPIOE, &gpio);
// CS
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOD, &gpio);
// RS
gpio.GPIO_Pin = GPIO_Pin_11 ;
GPIO_Init(GPIOD, &gpio);
// CS -> 1
// Reset -> 0
// RD -> 1
// RW -> 1
GPIO_SetBits(GPIOD, GPIO_Pin_7);
GPIO_ResetBits(GPIOE, GPIO_Pin_1);
GPIO_SetBits(GPIOD, GPIO_Pin_4);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
// Настройка FSMC
fsmcTiming.FSMC_AddressSetupTime = 0x02;
fsmcTiming.FSMC_AddressHoldTime = 0x00;
fsmcTiming.FSMC_DataSetupTime = 0x04;//0x05
fsmcTiming.FSMC_BusTurnAroundDuration = 0x00;
fsmcTiming.FSMC_CLKDivision = 0x00;
fsmcTiming.FSMC_DataLatency = 0x00;
fsmcTiming.FSMC_AccessMode = FSMC_AccessMode_B;
fsmc.FSMC_Bank = FSMC_Bank1_NORSRAM1;
fsmc.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
fsmc.FSMC_MemoryType = FSMC_MemoryType_NOR;
fsmc.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
fsmc.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
fsmc.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
fsmc.FSMC_WrapMode = FSMC_WrapMode_Disable;
fsmc.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
fsmc.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
fsmc.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
fsmc.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
fsmc.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
fsmc.FSMC_ReadWriteTimingStruct = &fsmcTiming;
fsmc.FSMC_WriteTimingStruct = &fsmcTiming;
fsmc.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInit(&fsmc);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
rotation = 1;
_width = TFTWIDTH;
_height = TFTHEIGHT;
}
/*******************************************************************/
void initLCD()
{
// Глобальный Reset дисплея
Global_reset();
// Пляски с бубном от китайских товарищей
LCD_Write_COM(0x01); //reset
delay(15);
LCD_Write_COM(0x11);//sleep out
delay(20);
LCD_Write_COM(0x28); //display off
delay(5);
LCD_Write_COM(0xCF); //power control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0xC1); //83 81 AA
LCD_Write_DATA(0x30);
LCD_Write_COM(0xED); //power on seq control
LCD_Write_DATA(0x64); //64 67
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x12);
LCD_Write_DATA(0x81);
LCD_Write_COM(0xE8); //timing control a
LCD_Write_DATA(0x85);
LCD_Write_DATA(0x00); // 01
LCD_Write_DATA(0x78); //79 78
LCD_Write_COM(0xCB); //power control a
LCD_Write_DATA(0x39);
LCD_Write_DATA(0X2C);
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x34);
LCD_Write_DATA(0x02);
LCD_Write_COM(0xF7); //pump ratio control
LCD_Write_DATA(0x20);
LCD_Write_COM(0xEA); //timing control b
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xC0); //power control 2
LCD_Write_DATA(0x23); //26 25
LCD_Write_COM(0xC1); //power control 2
LCD_Write_DATA(0x10);// 11
LCD_Write_COM(0xC5); //vcom control 1
LCD_Write_DATA(0x3E);// 35
LCD_Write_DATA(0x28);// 3E
LCD_Write_COM(0xC7); //vcom control 2
LCD_Write_DATA(0x86); //BE 94
LCD_Write_COM(0xB1); //frame control
LCD_Write_DATA(0x00);
LCD_Write_DATA(0x18); //1B 70
LCD_Write_COM(0xB6); //display control
LCD_Write_DATA(0x08);// 0A
LCD_Write_DATA(0x82);
LCD_Write_DATA(0x27);
LCD_Write_DATA(0x00);
LCD_Write_COM(0xB7); //emtry mode
LCD_Write_DATA(0x07);
LCD_Write_COM(0x3A); //pixel format
LCD_Write_DATA(0x55); //16bit
LCD_Write_COM(0xE0);
LCD_Write_DATA(0x0F);
LCD_Write_DATA(0x31);
LCD_Write_DATA(0x2B);
LCD_Write_DATA(0x0C);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x08);
LCD_Write_DATA(0x4E);
LCD_Write_DATA(0xF1);
LCD_Write_DATA(0x37);
LCD_Write_DATA(0x07);
LCD_Write_DATA(0x10);
LCD_Write_DATA(0x03);
LCD_Write_DATA(0x0E);
LCD_Write_DATA(0x09);
LCD_Write_DATA(0x00);
LCD_Write_COM(0x36); //mem access
LCD_Write_DATA((1<<3)|(1<<6));
//LCD_Write_DATA((1<<3)|(1<<7)); //rotate 180
LCD_Write_COM(0x29); //display on
LCD_Write_COM(0x2C);
delay(5);
/*writeLCDCommand(0x0015,0x0030);
writeLCDCommand(0x0011,0x0040);
writeLCDCommand(0x0010,0x1628);
writeLCDCommand(0x0012,0x0000);
writeLCDCommand(0x0013,0x104d);
delay(10);
writeLCDCommand(0x0012,0x0010);
delay(10);
writeLCDCommand(0x0010,0x2620);
writeLCDCommand(0x0013,0x344d);
delay(10);
writeLCDCommand(0x0001,0x0100);
writeLCDCommand(0x0002,0x0300);
writeLCDCommand(0x0003,0x1030);
writeLCDCommand(0x0008,0x0604);
writeLCDCommand(0x0009,0x0000);
writeLCDCommand(0x000A,0x0008);
writeLCDCommand(0x0041,0x0002);
writeLCDCommand(0x0060,0x2700);
writeLCDCommand(0x0061,0x0001);
writeLCDCommand(0x0090,0x0182);
writeLCDCommand(0x0093,0x0001);
writeLCDCommand(0x00a3,0x0010);
delay(10);
// Настройки гаммы
writeLCDCommand(0x30,0x0000);
writeLCDCommand(0x31,0x0502);
writeLCDCommand(0x32,0x0307);
writeLCDCommand(0x33,0x0305);
writeLCDCommand(0x34,0x0004);
writeLCDCommand(0x35,0x0402);
writeLCDCommand(0x36,0x0707);
writeLCDCommand(0x37,0x0503);
writeLCDCommand(0x38,0x1505);
writeLCDCommand(0x39,0x1505);
delay(10);
// Включение дисплея
writeLCDCommand(0x0007,0x0001);
delay(10);
writeLCDCommand(0x0007,0x0021);
writeLCDCommand(0x0007,0x0023);
delay(10);
writeLCDCommand(0x0007,0x0033);
delay(10);
writeLCDCommand(0x0007,0x0133);*/
}
/*******************************************************************/
int main()
{
initAll();
delay(100);
initLCD();
//setRotation(0);
while(1)
{
int i;
// Начальный и конечный адреса по горизонтали
/*writeLCDCommand(0x0050, 0);
writeLCDCommand(0x0051, 239);
// Начальный и конечный адреса по вертикали
writeLCDCommand(0x0052, 0);
writeLCDCommand(0x0053, 319);
writeLCDCommand(32, 0);
writeLCDCommand(33, 0);*/
//drawPixel(30, 40, 0xFFFF);
//LCD_Write_COM(0x51);
//LCD_Write_DATA(0x00);
//*(uint16_t *) (LCD_REG) = 0x2C;
// Красный
//fillScreen(0xF800);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xF800);
//drawPixel(30, 40, 0x0000);
}*/
//drawPixel(30, 40, 0x0000);
//delay(0xFFFFFF);
// Зеленый
//fillScreen(0x07E0);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x07E0);
}*/
//delay(0xFFFFFF);
//Синий
//fillScreen(0x001F);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x001F);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//Серый
//fillScreen(0x03EF);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x03EF);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//fillScreen(0xFFE0);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0xFFE0);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
//fillScreen(0x0000);
/*for (i = 0; i < 76800; i++)
{
LCD_Write_DATA(0x0000);
//drawPixel(30, 40, 0x0000);
}*/
//delay(0xFFFFFF);
for(i = 0; i < 4; i++)
{
setRotation(i);
fillScreen(0x03EF);
fillRect(20, 30, 50, 70, 0xF800);
delay(0x0FFFFF);
}
}
}
/*void Adafruit_GFX(int16_t w, int16_t h)
{
WIDTH(w), HEIGHT(h);
}*/
void Rotation(uint8_t x) {
rotation = (x & 3);
switch(rotation) {
case 0:
case 2:
_width = TFTWIDTH;
_height = TFTHEIGHT;
break;
case 1:
case 3:
_width = TFTHEIGHT;
_height = TFTWIDTH;
break;
}
}
void setRotation(uint8_t x)
{
Rotation(x);
uint16_t t;
switch (rotation) {
case 2:
//Rotation(x);
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR;
break;
case 3:
//Rotation(x);
t = ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
break;
case 0:
//Rotation(x);
t = ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR;
break;
case 1:
//Rotation(x);
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
break;
}
LCD_Write_COM(ILI9341_MADCTL); // MADCTL
LCD_Write_DATA(t);
// For 9341, init default full-screen address window:
setAddrWindow(0, 0, _width - 1, _height - 1);
}
void setAddrWindow(int x1, int y1, int x2, int y2)
{
uint32_t t;
t = x1;
t <<= 16;
t |= x2;
writeRegister32(ILI9341_COLADDRSET, t); // HX8357D uses same registers!
t = y1;
t <<= 16;
t |= y2;
writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers!
}
void fillRect(int16_t x1, int16_t y1, int16_t w, int16_t h, uint16_t fillcolor)
{
int16_t x2, y2;
// Initial off-screen clipping
if( (w <= 0 ) || (h <= 0 ) ||
(x1 >= _width) || (y1 >= _height) ||
((x2 = x1+w-1) < 0 ) || ((y2 = y1+h-1) < 0 )) return;
if(x1 < 0) { // Clip left
w += x1;
x1 = 0;
}
if(y1 < 0) { // Clip top
h += y1;
y1 = 0;
}
if(x2 >= _width) { // Clip right
x2 = _width - 1;
w = x2 - x1 + 1;
}
if(y2 >= _height) { // Clip bottom
y2 = _height - 1;
h = y2 - y1 + 1;
}
setAddrWindow(x1, y1, x2, y2);
flood(fillcolor, (uint32_t)w * (uint32_t)h);
}
void fillScreen(uint16_t color)
{
setAddrWindow(0, 0, _width - 1, _height - 1);
flood(color, (long)TFTWIDTH * (long)TFTHEIGHT);
}
void flood(uint16_t color, uint32_t len)
{
uint16_t blocks;
int i;
LCD_Write_COM(0x2c);
LCD_Write_DATA(color);
len--;
blocks = (uint16_t)(len / 64); // 64 pixels/block
while(blocks--) {
i = 16; // 64 pixels/block / 4 pixels/pass
do {
LCD_Write_DATA(color); LCD_Write_DATA(color);
LCD_Write_DATA(color); LCD_Write_DATA(color);
} while(--i);
}
for(i = (uint8_t)len & 63; i--; ) {
LCD_Write_DATA(color);
}
}
void drawPixel(int16_t x, int16_t y, uint16_t color)
{
setAddrWindow(x, y, _width-1, _height-1);
*(uint16_t *) (LCD_REG) = 0x2C;
LCD_Write_DATA(color);
}
void writeRegister32(uint16_t r, uint32_t d)
{
//CS_ACTIVE;
//CD_COMMAND;
LCD_Write_COM(r);
//write8(r);
//CD_DATA;
delay(DELAY_TIME);
LCD_Write_DATA(d>>24);
//write8(d >> 24);
delay(DELAY_TIME);
LCD_Write_DATA(d>>16);
//write8(d >> 16);
delay(DELAY_TIME);
LCD_Write_DATA(d>>8);
//write8(d >> 8);
delay(DELAY_TIME);
LCD_Write_DATA(d);
//CS_IDLE;
}
/*******************************************************************/
This code looks promising but I get the error: stm32f10x_gpio.h: No such file or directory
I tried copying that file everywhere, but no luck.
Help would be very much appreciated.
simple google for ili9325 gives 2nd link as
https://www.adafruit.com/product/335
and the 3rd link as
http://tronixstuff.com/2013/04/26/tutor … d-modules/
stephen
The libmaple core does not use the CMSIS because of historical licensing issues.
You will need to comment out that include, and then see what functions are called, and them change the library to use the libmaple equivalent functions, or possibly manipulate the hardware directly.
But I’ve been working on the HAL as a library.
I’m not sure if one library can include another library, but this may be a way to port some code based on the CMSIS albeit as long as that code is compatible with the CMSIS that is generated by the STM Cube
<…>
I’m not sure if one library can include another library<…>
The HAl library, isnt really a library, its just a way to get the IDE to compile and link the STM HAL files, and read in all the headers, so that the HAL functions can be called inside the sketch.
The HAL is written in C, and seems to just be a load of disparate files, each with a grouped set of functions in them.
But its a lot of files, I have not counted them, but it looks like 100’ish, and takes up several megabytes.
Anyway, its rather experimental at the moment, but may be useful to some people.
<…>
The HAl library, isnt really a library, its just a way to get the IDE to compile and link the STM HAL files, and read in all the headers, so that the HAL functions can be called inside the sketch.
<…>
But its a lot of files, I have not counted them, but it looks like 100’ish, and takes up several megabytes.
<….
This confusion is my fault.
I am playing fast and loose with the Arduino Library paradigm with this.
I bent the rules a bit with the Libraries system, in the past, by making an empty library, just to put our examples in; so they can be acccessed via the menu system.
But in this case, the header does actually include some files, and the IDE does have to compile a whole loadmof files, but none of them, AFIK, are classes.
I may even remove the dummy HAL class I made, as it may not be needed at all, depending on whether any initialisation code needed to be run – and at the moment, it looks like running the default HAL_init() function screws things up, as it either messes up the clock PLLs or possibly does something strange to systick, ( I have not had time to investigate precislely what its affecting, so I am not calling HAL_init() from the library at the moment)
With your help of martinayotte, werefcat and diger67’s posts in http://www.stm32duino.com/viewtopic.php?f=9&t=474 I managed to port the SPI version of ILI9341 library to work with 8 bit parallel.
viewtopic.php?f=44&t=637&p=15438#p15438
github:
https://github.com/iwalpola/Adafruit_ILI9341_8bit_STM/
demo:
https://www.youtube.com/watch?v=MAkMaZyZMWM
In my case with Netduino2Plus pinouts as uint8_t DPINS[] = {PC7, PC6, PA3, PA2, PB12, PB8, PB9, PA1, PA0, PA6};, I don’t think I could get much speed optimisation doing direct register access …
I’m also curious to know the performance as compared to SPI.
Benchmark Time (microseconds)
Screen fill 1478774
Text 43997
Lines 376454
Horiz/Vert Lines 101883
Rectangles (outline) 65100
Rectangles (filled) 3070377
Circles (filled) 419900
Circles (outline) 285285
Triangles (outline) 90139
Triangles (filled) 713698
Rounded rects (outline) 131807
Rounded rects (filled) 3324904
Done!
Benchmark Time (microseconds)
Screen fill 1478774
Text 43997
Lines 376454
Horiz/Vert Lines 101883
Rectangles (outline) 65100
Rectangles (filled) 3070377
Circles (filled) 419900
Circles (outline) 285285
Triangles (outline) 90139
Triangles (filled) 713698
Rounded rects (outline) 131807
Rounded rects (filled) 3324904
Done!
@Martin Perhaps it comes down to the GFX library functions?
Very curious indeed
I looked at some previous postings to the forum e.g. http://www.stm32duino.com/viewtopic.php?t=862&start=40
and it looks like operations which set individual pixels are faster, but anything that fills large areas are slower.
From what I recall the adafruit SPI based library is not very effecient at writing individual pixels, and I suspect that improvements could be made to the SPI version which may improve single pixel access speed in the SPI version.
(I think the Teensy has an optimised library with fast pixel access)
Where this really comes into its own, is on boards that use the F103V or F103Z, which have whole GPIO ports that are unused.
And further speed improvements can be gained where there are separate data and address ports.
the drawpixel function wastes a lot of time, as it assumes its being called for a one off command, but as its called from the functions which draw triangles etc, it makes operations like triangles slow.
The simple solution, is to have 2 functions to write a pixel, one that works standalone and one that needs the SPI to be initialised for it e.g Chip Select pins etc to be toggled.
then get the triangle functions to call the non-standalone version.
Ideally the non-standalone function would be private to the class, but because the Text generator is in a separate cpp, I think to optimise the text, the new function would need to be made public, which is not ideal, but not something I would loose sleep over ![]()
void Adafruit_ILI9341_STM::drawPixel(int16_t x, int16_t y, uint16_t color) {
if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return;
if (hwSPI) spi_begin();
setAddrWindow(x, y, x + 1, y + 1);
*dcport |= dcpinmask;
*csport &= ~cspinmask;
spiwrite(color >> 8);
spiwrite(color);
*csport |= cspinmask;
if (hwSPI) spi_end();
}
However, on the line drawing, screen filling etc, where there is a lot of data to be written, there was room for improvement in CHIP_SELECT toggling and toggling of RS pin (which decides whether data written is command or data).
So after adjusting (after doing a git diff), the benchmark is better than Kurt’s mod!! Maybe there is room for even more improvement, but I guess this is pretty good.
Benchmark Time (microseconds)
Screen fill 784951
Text 27277
Lines 242789
Horiz/Vert Lines 66034
Rectangles (outline) 42204
Rectangles (filled) 1630078
Circles (filled) 240487
Circles (outline) 180967
Triangles (outline) 58242
Triangles (filled) 563808
Rounded rects (outline) 84634
Rounded rects (filled) 1777583
Does the parallel version toggle CS etc for every pixel, or did you optimise it?
Does the parallel version toggle CS etc for every pixel, or did you optimise it?
It was doing CS toggle for every pixel write earlier (my dumb idea). Now I fixed it.
I was worried that it will interfere with the touch digitizer output available in the same module (TFT and Touch share 4 pins).
On every parallel 8bis transfer, there must be an CS pulse.
So, how can that be skipped for optimisation ?
The other line that has to be toggled a lot is the Data / command pin
It looks like the main reason that writing single pixels is slow is not the CS line but the unnecessary calling of SPI begin transaction before writing each pixel, which takes up a huge amount of time, as the whole SPI device has to be disabled and all settings updated etc etc etc
Some minimal changes would result in a massive speed improvement in some functions e.g. drawing of diagonal lines , but the Adafruit graphics lib would need to also be updated to yield faster text speeds.
If I get time this evening, I will take a quick look at the existing code in the Adafruit_ili9341_STM lib (for F1)
Demo (almost too fast to see):
https://youtu.be/sGU_wwX20hM
@Roger, there must surely be potential for improvement in the SPI code as well. What I learned today is that even microseconds worth of delay adds up fast when you repeat it 10000’s of times.
Benchmark Time (microseconds)
Screen fill 320577
Text 14869
Lines 129592
Horiz/Vert Lines 25437
Rectangles (outline) 16493
Rectangles (filled) 666012
Circles (filled) 104502
Circles (outline) 96406
Triangles (outline) 30358
Triangles (filled) 230338
Rounded rects (outline) 41103
Rounded rects (filled) 709046
Done!
Re: SPI version
Yes.
Now I look at the code, there is loads of room for improvement, and like you said, even a few uS shaved off here and there in the low level functions make a big difference.
What is still slower for you is the fill stuff as you can’t benefit from DMA. Well, if the pins were adjacent from the beginning of a port you could use DMA as you can DMA to GPIO (but we don’t have any demo code for this)
But as you use pins all over the board, DMA will not really help ![]()
Demo (almost too fast to see):
https://youtu.be/sGU_wwX20hM
@Roger, there must surely be potential for improvement in the SPI code as well. What I learned today is that even microseconds worth of delay adds up fast when you repeat it 10000’s of times.
Benchmark Time (microseconds)
Screen fill 320577
Text 14869
Lines 129592
Horiz/Vert Lines 25437
Rectangles (outline) 16493
Rectangles (filled) 666012
Circles (filled) 104502
Circles (outline) 96406
Triangles (outline) 30358
Triangles (filled) 230338
Rounded rects (outline) 41103
Rounded rects (filled) 709046
Done!
Re: SPI version
Yes.
Now I look at the code, there is loads of room for improvement, and like you said, even a few uS shaved off here and there in the low level functions make a big difference.
What is still slower for you is the fill stuff as you can’t benefit from DMA. Well, if the pins were adjacent from the beginning of a port you could use DMA as you can DMA to GPIO (but we don’t have any demo code for this)
Can you post the code to your sketch that you use for those timing results, as I don’t think its the same sketch that I am using to compare SPI speeds
(Or post a link to the sketch source code)
Thanks
Roger
Benchmark Time (microseconds)
Screen fill 320577
...
Benchmark Time (microseconds)
Screen fill 170787
Text 22869
Lines 241990
Horiz/Vert Lines 15802
Rectangles (outline) 11547
Rectangles (filled) 355060
Circles (filled) 142830
Circles (outline) 173697
Triangles (outline) 59139
Triangles (filled) 165883
Rounded rects (outline) 59967
Rounded rects (filled) 415460
Do we know what the absolute limits of the display are, in terms of speed?
I do not work in an environment with Arduino STM. But can someone come in handy. Here are a few defines. Their work is checked in Keil. Binding conclusions made to the standard location pins Shild TFT for Arduino. New definition write8inline (d) is faster than the previous version.
//Port data |D7 | D6 |D5 |D4 |D3 | D2 |D1 |D0 |
//Pin stm32 |PA8|PB10|PB4|PB5|PB3|PA10|PC7|PA9|
//control port |RST| CS | RS | WR| RD|
//Pin stm32 |PC0|PB0|PA4|PA1|PA0|
#define write8inline(d) {\
GPIOA->BSRR = (data & (1<<0)) ? GPIO_BSRR_BS9 : GPIO_BSRR_BR9;\
GPIOC->BSRR = (data & (1<<1)) ? GPIO_BSRR_BS7 : GPIO_BSRR_BR7;\
GPIOA->BSRR = (data & (1<<2)) ? GPIO_BSRR_BS10 : GPIO_BSRR_BR10;\
GPIOB->BSRR = (data & (1<<3)) ? GPIO_BSRR_BS3 : GPIO_BSRR_BR3;\
GPIOB->BSRR = (data & (1<<4)) ? GPIO_BSRR_BS5 : GPIO_BSRR_BR5;\
GPIOB->BSRR = (data & (1<<5)) ? GPIO_BSRR_BS4 : GPIO_BSRR_BR4;\
GPIOB->BSRR = (data & (1<<6)) ? GPIO_BSRR_BS10 : GPIO_BSRR_BR10;\
GPIOA->BSRR = (data & (1<<7)) ? GPIO_BSRR_BS8 : GPIO_BSRR_BR8;\
WR_STROBE;\
}
#define enportrcc() {\
RCC->APB2ENR |= ((RCC->APB2ENR &= 0xFFFFFFFF) | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN);\
AFIO->MAPR |= ((AFIO->MAPR &= 0xFFFFFFFF) | AFIO_MAPR_SWJ_CFG_JTAGDISABLE);\
GPIOA->CRL = ((GPIOA->CRL &= 0xFFF0FF00) | 0x00030033); \
GPIOC->CRL = ((GPIOC->CRL &= 0xFFFFFF0F) | 0x00000030); \
GPIOB->CRL = ((GPIOB->CRL &= 0xFFFFFFF0) | 0x00000003); \
}
#define setWriteDirInline() { \
GPIOA->CRH = ((GPIOA->CRH &= 0xFFFFF000) | 0x00000333); \
GPIOC->CRL = ((GPIOC->CRL &= 0x0FFFFFFF) | 0x30000000); \
GPIOB->CRL = ((GPIOB->CRL &= 0xFF000FFF) | 0x00333000); \
GPIOB->CRH = ((GPIOB->CRH &= 0xFFFFF0FF) | 0x00000300); \
}
#define setReadDirInline() { \
GPIOA->CRH = ((GPIOA->CRH &= 0xFFFFF000) | 0x00000444); \
GPIOC->CRL = ((GPIOC->CRL &= 0x0FFFFFFF) | 0x40000000); \
GPIOB->CRL = ((GPIOB->CRL &= 0xFF000FFF) | 0x00444000); \
GPIOB->CRH = ((GPIOB->CRH &= 0xFFFFF0FF) | 0x00000400); \
}
#define enportrcc() {\
RCC->APB2ENR |= ((RCC->APB2ENR &= 0xFFFFFFFF) | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN);\
AFIO->MAPR |= ((AFIO->MAPR &= 0xFFFFFFFF) | AFIO_MAPR_SWJ_CFG_JTAGDISABLE);\
Are you trying to clear the APB2ENR register with the &= ((RCC->APB2ENR &= 0xFFFFFFFF) ?
It is probably easier to set it to zero or use &= ((RCC->APB2ENR &= ~0xFFFFFFFF)
Or maybe I misunderstand what you are doing there.
-rick
Are you trying to clear the APB2ENR register with the &= ((RCC->APB2ENR &= 0xFFFFFFFF) ?
It is probably easier to set it to zero or use &= ((RCC->APB2ENR &= ~0xFFFFFFFF)
Or maybe I misunderstand what you are doing there.
-rick
Also, I had to stick to digital write and read functions, because the pure register writes for pin toggling was too fast and the screen went blank!
Here my benchmark using Adafruit original graphic test ino:
TFT LCD test
TFT size is 240x320
Found ILI9328 LCD driver
Benchmark Time (microseconds)
Screen fill 1019555
Text 115645
Lines 719977
Horiz/Vert Lines 96056
Rectangles (outline) 69857
Rectangles (filled) 2155387
Circles (filled) 843279
Circles (outline) 313036
Triangles (outline) 228363
Triangles (filled) 993928
Rounded rects (outline) 146794
Rounded rects (filled) 2514008
Done!
TFT LCD test
TFT size is 240x320
Found ILI9328 LCD driver
Benchmark Time (microseconds)
Screen fill 65561
Text 24708
Lines 141805
Horiz/Vert Lines 8723
Rectangles (outline) 7335
Rectangles (filled) 155516
Circles (filled) 134162
Circles (outline) 60283
Triangles (outline) 45012
Triangles (filled) 115087
Rounded rects (outline) 24511
Rounded rects (filled) 206878
Done!
rotation: 0, text runtime: 24708
rotation: 1, text runtime: 24972
rotation: 2, text runtime: 24973
rotation: 3, text runtime: 24985
line 84
#define read8(x) { x = read8_() ;}
===================================
line 84
#define read8(x) { x = read8_() ;}



