+7(960) 250-82-68 spam@mirossa.ru


 mirossa        1С           C         PHP       JAVA       MCU  


Статьи
 
 
Работа по учебнику Discovering the STM32 Microcontroller by Geoffrey Brown. главы 7 + 8.

STM32 + ST7735 + SD card. Интерфейс SPI.

При нажатии кнопки "на stm32" на дисплее последовательно отображаются: текстовая строка, изображения из bitmap файла(считываются с SD карты), графические примитивы (линии, окружности), меняется расположение осей X и Y.

Для работы с SD картой использован модуль FatFs версии R0.09 .

ST7735R цветной TFT LCD со слотом для MicroSD карты (это клон Adafruit Mini TFT - 0.96" 160x80; https://www.adafruit.com/product/3533 (почему-то только через TOR) ).
У этого клона начальная координата - (24,0), а не (0,0). Если поменять оси X и Y местами (функции дисплея), то (0,24). Добавил этот нюанс в функции, чтобы на уровне приложения задавать привычные (0,0).

datasheet ST7735R v1.4

Весь исходный код. ide CooCox.

connection STM32 and 25LC160

некоторые модули:

/* main.c */
#include <stm32f10x.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_spi.h>
#include "lcd_st7735.h"
#include <string.h>
#include "ff.h"

extern uint8_t ST7735_width_curr;
extern uint8_t ST7735_height_curr;

UINT bw, br;
FIL Fil1;
FILINFO fno;        /* FILINFO structure */
FATFS Fatfs;
FRESULT frez;

// bmp24 b
//  https://studassistent.ru/c/otobrazhenie-kartinki-bmp-c-si
struct
    {
        short signature;
        int size;
        int adress;
        int lengthHead;
        int length;
        int heigh;
        short numColPlosk;
        short bitPerPix;
        int comprMet;
        int arrLength;
        int gorResolution;
        int vertResolution;
        int numColors;
        int numMainColors;
    } headBMP;

char pic[480];      // BGR BGR BGR ...  // 1 line = 160 px * 3 byte; для ширины в 160 пикселей
uint8_t readPic(char *path);
uint8_t writePic(char *path);
void verticalReflectC(void);

uint8_t readAndPrintBMP();
// bmp24 e

void fillScreen(uint16_t color);
void otherInit(void);

//void Delay(uint32_t nTime);
uint8_t debounce(uint8_t last);

#define rlen 80

int main(void)
{
	uint8_t currentButton;
	uint8_t lastButton;
	uint8_t rej = 0;

	char Buff[70];

	otherInit(); // Initialize user button
	ST7735_init();
	ST7735_backLight(1);

	lastButton = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	currentButton = lastButton;

	// Configure SysTick Timer
	//if (SysTick_Config(SystemCoreClock / 1000))
			//while (1);

	fillScreen(ST7735_GREEN);

while (1)	{

	currentButton = debounce(lastButton);

	if ( lastButton == Bit_RESET && currentButton == Bit_SET ){

		if ( rej == 0 ){
			rej++;
			//outChar('X', ST7735_YELLOW, ST7735_BLACK);
			printStr("Let's get started. Here are print of string, read of bitmaps from SD card and "
					"display of them, draw primitive figures.", -1, -1, ST7735_YELLOW, ST7735_BLACK);

		}
		else if ( rej == 1 ){
			rej++;

			if( f_mount(0, &Fatfs) == FR_OK) {

				if ( ( frez = f_open (&Fil1 , "1_40x40.bmp", FA_READ) ) == FR_OK) {

					readAndPrintBMP();
					frez = f_close(&Fil1);

				}else{
					printStr("File is not opened for read.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
				 }

				frez = f_mount(0, NULL);

			} else{
				printStr("Volume was not mounted.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
			}

		} else if ( rej == 2 ){
			rej++;

			fillRect(0, 0, 159, 79, ST7735_WHITE);
			fillRect(10, 13, 140, 40, ST7735_MAGENTA);
			DrawRectangle(3,30, 80, 75, 2, ST7735_CYAN);
			DrawLine(2,3, 149, 50, ST7735_BLACK);
			DrawLine(2,50, 149, 3, ST7735_BLACK);
			DrawCircleBresenham(80, 40, 35, ST7735_RED);

		}else if ( rej == 3 ){
			rej++;

			if( f_mount(0, &Fatfs) == FR_OK) {    // Register volume work area

				// READ

				if ( ( frez = f_open (&Fil1 , "2.bmp", FA_READ) ) == FR_OK) {

					readAndPrintBMP();
					frez = f_close(&Fil1);

				}else{
					printStr("File is not opened for read.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
				 }

				// MAKE DIR, SET CURRENT DIR

				frez = f_stat ( "/files", &fno);
				if ( frez == FR_OK ){
					frez = f_chdir("/files");

				}else if ( frez == FR_NO_PATH ){
					frez = f_mkdir("/files");
					if ( frez == FR_OK )
						frez = f_chdir("/files");

				}else{

				}

				// WRITE

				if ( ( frez = f_open (&Fil1 , "HELLO.TXT", FA_WRITE | FA_CREATE_ALWAYS) ) == FR_OK) {
					if ( ( frez = f_write (&Fil1 , "Hello world !\r\n", 14, &bw) ) == FR_OK ){
						frez = f_close (&Fil1);
					}else{
						printStr("Error of recording to file.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
					}
				}else{
					printStr("File is not opened for write.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
				 }

			frez = f_mount(0, NULL);

			} else{
				printStr("Volume was not mounted.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
			}

		} else if ( rej == 4 ){
			rej++;

			ST7735_setMadctl(MADCTLGRAPHICS_normal);
			fillScreen(ST7735_CYAN);

			//outChar('O', ST7735_YELLOW, ST7735_BLACK);


		} else {
			rej = 0;

			if( f_mount(0, &Fatfs) == FR_OK) {

				if ( ( frez = f_open (&Fil1 , "1_40x40.bmp", FA_READ) ) == FR_OK) {

					readAndPrintBMP();
					frez = f_close(&Fil1);

				}else{
				 printStr("File is not opened for read.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
				 }

				frez = f_mount(0, NULL);

			} else{
				printStr("Volume was not mounted.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
			}

		}
	}

	lastButton = currentButton;

}//while

    return 0;
}

void otherInit(void){
	GPIO_InitTypeDef GPIO_InitStructure;


	// user button A0
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_Init(GPIOA,	&GPIO_InitStructure);
}

/*static __IO uint32_t TimingDelay;

void Delay(uint32_t nTime){
	TimingDelay = nTime;
	while(TimingDelay != 0);
}


void SysTick_Handler(void){
	if (TimingDelay != 0x00)
		TimingDelay--;
}
*/

// обработка дребега контакта кнопки
uint8_t debounce(uint8_t last){
	uint8_t current = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	  if ( last != current ){
		  Delay(5);
		  current = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	  }
  return current;
}

//вместо этой функции(медленная) лучше использовать fillRect()
void fillScreen(uint16_t color){
	uint8_t x, y;
	ST7735_setAddrWindow(0, 0, ST7735_width_curr-1, ST7735_height_curr-1);
	for ( x=0; x < ST7735_width_curr; x++ ) {
		for ( y=0; y < ST7735_height_curr; y++ ) {
			ST7735_pushColor(&color, 1);
		}
	}
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
	/* Infinite loop */
	/* Use GDB to find out why we're here */
	while (1);
}
#endif

// работа с 24-битным bitmap.
// оперативной памяти под целый bmp файл ( > 38Kb для 160x80 пикселей ) не хватит.
// поэтому из файла (на SD карте) считывается, и выводится на экран, по одной "пиксельной"
// строке за раз. Bitmap выводится в "верхний левый" угол экрана. Если ширина/длина дисплея
// больше чем у bmp, то изображение будет занимать часть экрана.
// Если ширина/длина дисплея меньше, чем размер bmp, то из файла будут считываться
// пиксельные строки по ширине экрана, часть выходящая за экран отбрасывается(не считывается).
// Если по какой-то причине(редкой) из файла будет прочитано меньше, чем запрошено, то строка
// будет выведена не полностью, а управление перейдёт на вывод следующей строки.
uint8_t readAndPrintBMP() {
        long int i, y;
        uint8_t d, n;
        uint16_t cr, bytePerLine, cc;

	frez = f_read (&Fil1 , &headBMP.signature , sizeof(short), &br);
	if (frez || !br){
		printStr("read error.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
		return 1;
	}
	if(headBMP.signature != (short)0x4d42){
		printStr("File is not bmp.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
		return 1;
	}
	else
	{
		f_read (&Fil1 , &headBMP.size , sizeof(int), &br);
		f_lseek(&Fil1, f_tell(&Fil1) + 2*sizeof(short));
		f_read (&Fil1 , &headBMP.adress , sizeof(int), &br);
		f_read (&Fil1 , &headBMP.lengthHead , sizeof(int), &br);
		f_read (&Fil1 , &headBMP.length , sizeof(int), &br);
		f_read (&Fil1 , &headBMP.heigh , sizeof(int), &br);
		f_read (&Fil1 , &headBMP.numColPlosk , sizeof(short), &br);
		f_read (&Fil1 , &headBMP.bitPerPix , sizeof(short), &br);
		if (headBMP.bitPerPix != (short)24) {
			printStr("Bmp is not 24.", -1, -1, ST7735_MAGENTA, ST7735_WHITE);
			return 1;
		}
		else {
			f_read (&Fil1 , &headBMP.comprMet , sizeof(int), &br);
			f_read (&Fil1 , &headBMP.arrLength , sizeof(int), &br);
			f_read (&Fil1 , &headBMP.gorResolution , sizeof(int), &br);
			f_read (&Fil1 , &headBMP.vertResolution , sizeof(int), &br);
			f_read (&Fil1 , &headBMP.numColors , sizeof(int), &br);
			f_read (&Fil1 , &headBMP.numMainColors , sizeof(int), &br);
		}

	}

	frez = f_lseek(&Fil1, 54*sizeof(char));

	// что меньше ширина/высота в файле или текущая ширина/высота экрана
	cr = ( headBMP.heigh > ST7735_height_curr) ?  ST7735_height_curr: headBMP.heigh; //row
	cc = ( headBMP.length > ST7735_width_curr) ?  ST7735_width_curr: headBMP.length; //col

	bytePerLine = cc * 3;

	// (командой MADCTL (36h) можно выбрать расшифровку значения цветов - RGB  или BGR. сейчас - RGB)
	// в bmp файле каналы цвета располагаются в GBR порядке.
	// преобразую BGR 24-бит в RGB 16-бит с учётом того, что формирую последовательность
	// байтов цветов в массиве CHAR, а затем функция lcd_printPixelLine работает с ним
	// как с массивом uint16_t (порядок байт не "mb lb", а "lb mb")
	for (i = 0; i < cr; i++){

		frez = f_read (&Fil1 , pic , bytePerLine, &br);
		if ( frez != FR_OK)
			break;

		n = br/3; // count of pixels
		for ( y = 0; y < n; y++){

			pic[y*2] = pic[y*3] >> 3; // B сдвигается вправо
			pic[y*2] |= (pic[y*3+1] & 0x1C) << 3; //слева от B добавляюся 3 старших бита G
			pic[y*2+1] = pic[y*3+1] >> 5; // R сдвигается вправо
			pic[y*2+1] |= (pic[y*3+2] & 0xF8) ; //к R присоединяются 3 средних бита G

		}
		// строки в bmp располагаются в обратном порядке в направлении заголовков
		// считываю строки в ЭТОМ порядке, а вывожу снизу вверх.
		lcd_printPixelLine(cr - 1 - i, (uint16_t *)pic, n);

		if ( bytePerLine != br || cc < headBMP.length )
			frez = f_lseek(&Fil1, 54*sizeof(char) + 3*headBMP.length* (i+1) );
	}

	return 0;


}


/*lcd_st7735.c*/

//Copyright Information

//Our code for the ST7335 is derived from a module available from https:
//github.com/adafruit/Adafruit-ST7735-Library.git

//The following copyright applies to that code:
/***************************************************
This is a library for the Adafruit 1.8" SPI display.
This library works with the Adafruit 1.8" TFT Breakout w/SD card
----> http://www.adafruit.com/products/358

as well as Adafruit raw 1.8" TFT display
----> http://www.adafruit.com/products/618
Check out the links above for our tutorials and wiring diagrams
These displays use SPI to communicate, 4 or 5 pins are required to
interface (RST is optional)
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
****************************************************/

#include <stm32f10x.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_spi.h>
#include "lcd_st7735.h"
#include "spi.h"
#include "glcdfont.h"
#include <string.h>
#include <math.h>

#define LOW 0
#define HIGH 1
#define LCD_C LOW
#define LCD_D HIGH
#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_MADCTL 0x36
#define ST7735_RAMWR 0x2C
#define ST7735_RAMRD 0x2E
#define ST7735_COLMOD 0x3A

// the book or's MADVAL with 0x08, which inverts the color order in my display
//(I think it depends on the version of 7735 you have)
#define MADVAL(x) (((x) << 5))   // (((x) << 5) | 8)

// для (MY,MX,MV)= (0, 1, 1)
static uint8_t StartPositionX = 0, StartPositionY = 24;
uint8_t ST7735_width_curr = 160;  //меняется на длину  при изменении MV
uint8_t ST7735_height_curr = 80; //меняется на ширину при изменении MV
uint8_t MV = 1;

//текущие координаты, с которых будет выведен символ
static uint8_t curX_PosChar = 0, curY_PosChar = 0;

#define LCD_PORT		GPIOC
#define GPIO_PIN_RST	GPIO_Pin_1
#define GPIO_PIN_DC		GPIO_Pin_2
#define GPIO_PIN_SCE	GPIO_Pin_0   //LCD select
#define SPILCD			SPI2
#define LCD_PORT_BKL	GPIOA
#define GPIO_PIN_BKL	GPIO_Pin_1
 // SD_CS PC6 SD card select
#define LCDSPEED		SPI_MEDIUM

struct ST7735_cmdBuf {
uint8_t command; // ST7735 command byte
uint8_t delay; // ms delay after
uint8_t len; // length of parameter data
uint8_t data [16]; // parameter data
};
static const struct ST7735_cmdBuf initializers [] = {
// SWRESET Software reset   10.1.2
{ 0x01 , 150, 0, {0}},
// SLPOUT Leave sleep mode  10.1.11
{ 0x11 , 150, 0, {0}},
// FRMCTR1 , FRMCTR2 Frame Rate configuration -- Normal mode , idle
// frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D)   10.2.1
{ 0xB1 , 0, 3, { 0x01 , 0x2C , 0x2D }},
{ 0xB2 , 0, 3, { 0x01 , 0x2C , 0x2D }},
// FRMCTR3 Frame Rate configureation -- partial mode
{ 0xB3 , 0, 6, { 0x01 , 0x2C , 0x2D , 0x01 , 0x2C , 0x2D }},
// INVCTR Display inversion (no inversion)
{ 0xB4 , 0, 1, { 0x07 }},
// PWCTR1 Power control -4.6V, Auto mode
{ 0xC0 , 0, 3, { 0xA2 , 0x02 , 0x84}},
// PWCTR2 Power control VGH25 2.4C, VGSEL -10, VGH = 3 * AVDD
{ 0xC1 , 0, 1, { 0xC5}},
// PWCTR3 Power control , opamp current smal , boost frequency
{ 0xC2 , 0, 2, { 0x0A , 0x00 }},
// PWCTR4 Power control , BLK/2, opamp current small and medium low
{ 0xC3 , 0, 2, { 0x8A , 0x2A}},
// PWRCTR5 , VMCTR1 Power control
{ 0xC4 , 0, 2, { 0x8A , 0xEE}},
{ 0xC5 , 0, 1, { 0x0E }},
// INVOFF Don't invert display
{ 0x20 , 0, 0, {0}},
// Memory access directions. row address/col address , bottom to  top refesh (10.1.27; 9.11.3)
{ ST7735_MADCTL , 0, 1, {MADVAL(MADCTLGRAPHICS)}},
// Color mode 16 bit (10.1.30
{ ST7735_COLMOD , 10, 1, {0x05}},
// Column address set 0..127
{ ST7735_CASET , 0, 4, {0x00 , 0x00 , 0x00 , 0x7F }},
// Row address set 0..159
{ ST7735_RASET , 0, 4, {0x00 , 0x00 , 0x00 , 0x9F }},
// GMCTRP1 Gamma correction
{ 0xE0 , 0, 16, {0x02 , 0x1C , 0x07 , 0x12 , 0x37 , 0x32 , 0x29 , 0x2D ,
0x29 , 0x25 , 0x2B , 0x39 , 0x00 , 0x01 , 0x03 , 0x10 }},
// GMCTRP2 Gamma Polarity corrction
{ 0xE1 , 0, 16, {0x03 , 0x1d , 0x07 , 0x06 , 0x2E , 0x2C , 0x29 , 0x2D ,
0x2E , 0x2E , 0x37 , 0x3F , 0x00 , 0x00 , 0x02 , 0x10 }},
// DISPON Display on
{ 0x29 , 100, 0, {0}},
// NORON Normal on
{ 0x13 , 10, 0, {0}},
// End
{ 0, 0, 0, {0}}
};

static void LcdWrite(char dc, const char * data, int nbytes){
	GPIO_WriteBit(LCD_PORT, GPIO_PIN_DC, dc); //dc 1 = data, 0 = control
	GPIO_ResetBits(LCD_PORT, GPIO_PIN_SCE);
	spiReadWrite(SPILCD, 0, data, nbytes, LCDSPEED);
	GPIO_SetBits(LCD_PORT, GPIO_PIN_SCE);
}

static void LcdWrite16(char dc, const uint16_t * data, int cnt){
	GPIO_WriteBit(LCD_PORT, GPIO_PIN_DC, dc); //dc 1 = data, 0 = control
	GPIO_ResetBits(LCD_PORT, GPIO_PIN_SCE);
	spiReadWrite16(SPILCD, 0, data, cnt, LCDSPEED);
	GPIO_SetBits(LCD_PORT, GPIO_PIN_SCE);
}

static void ST7735_writeCmd(uint8_t c){
	LcdWrite(LCD_C, &c, 1);
}

static uint8_t madctlcurrent = MADVAL(MADCTLGRAPHICS);

void ST7735_setMadctl(uint8_t madctl){
		madctl = MADVAL(madctl);
		if (madctl != madctlcurrent){
			ST7735_writeCmd(ST7735_MADCTL);
			LcdWrite(LCD_D , &madctl , 1);
			madctlcurrent = madctl;

			MV = (madctlcurrent & 0x20) == 0x20;
			if ( MV ) {
				StartPositionX = 0,
				StartPositionY = 24;
				ST7735_width_curr = 160;
				ST7735_height_curr = 80;
			} else {
				StartPositionX = 24,
				StartPositionY = 0;
				ST7735_width_curr = 80;
				ST7735_height_curr = 160;
			}
			curX_PosChar = 0;
			curY_PosChar = 0;
		}
}

void ST7735_setAddrWindow(uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1){

	uint16_t fx0;
	uint16_t fy0;
	uint16_t fx1;
	uint16_t fy1;


	fx0 = x0 + StartPositionX;
	fy0 = y0 + StartPositionY;
	fx1 = x1 + StartPositionX;
	fy1 = y1 + StartPositionY;

	ST7735_writeCmd(ST7735_CASET); //Column Address Set  10.1.19
	LcdWrite16(LCD_D , &fx0 , 1);
	LcdWrite16(LCD_D , &fx1 , 1);
	ST7735_writeCmd(ST7735_RASET); //Row Address Set  10.1.20
	LcdWrite16(LCD_D , &fy0 , 1);
	LcdWrite16(LCD_D , &fy1 , 1);
	ST7735_writeCmd(ST7735_RAMWR);
}

void ST7735_pushColor(uint16_t *color , int cnt){
	LcdWrite16(LCD_D , color , cnt);
}

static __IO uint32_t TimingDelay;

void Delay(uint32_t nTime){
	TimingDelay = nTime;
	while(TimingDelay != 0);
}


void SysTick_Handler(void){
	if (TimingDelay != 0x00)
		TimingDelay--;
}

void ST7735_init ()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	const struct ST7735_cmdBuf *cmd;

	//Configure SysTick Timer
	if (SysTick_Config(SystemCoreClock / 1000))
		while (1);

	// set up pins
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA , ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DC | GPIO_PIN_SCE | GPIO_PIN_RST; //GPIO_Pin_2 | GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //GPIO_Speed_50MHz;
	GPIO_Init(LCD_PORT,	&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_BKL;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //GPIO_Speed_50MHz;
	GPIO_Init(LCD_PORT_BKL,	&GPIO_InitStructure);


	/*Initialise SPI*/
		spiInit(SPILCD);

	// set cs , reset low
	GPIO_WriteBit(LCD_PORT ,GPIO_PIN_SCE , HIGH);
	GPIO_WriteBit(LCD_PORT ,GPIO_PIN_RST , HIGH);
	Delay (10);
	GPIO_WriteBit(LCD_PORT ,GPIO_PIN_RST , LOW);
	Delay (10);
	GPIO_WriteBit(LCD_PORT ,GPIO_PIN_RST , HIGH);
	Delay (10);
	// Send initialization commands to ST7735
	for (cmd = initializers; cmd ->command; cmd ++)	{
		LcdWrite(LCD_C , &(cmd ->command), 1);
		if (cmd ->len)
			LcdWrite(LCD_D , cmd ->data , cmd ->len);
		if (cmd ->delay)
			Delay(cmd ->delay);
	}
}

void ST7735_backLight(uint8_t on){
	if (on)
		GPIO_WriteBit(LCD_PORT_BKL ,GPIO_PIN_BKL , HIGH);
	else
		GPIO_WriteBit(LCD_PORT_BKL ,GPIO_PIN_BKL , LOW);
}

void printStr(char * str, int16_t X, int16_t Y, uint16_t foreground, uint16_t background){
	uint16_t i;

	if ( X != -1 )
		curX_PosChar = X;
	if ( Y != -1 )
		curY_PosChar = Y;

	for ( i = 0; i < strlen(str); i++ )
		outChar(str[i], foreground, background);
}

void outChar(uint8_t ch, uint16_t foreground, uint16_t background){
	//размер символа 5х8, размер символа на экране 6х10
	//(1 пиксель справа + 2 пикселя снизу)
	#define width (5+1) // ширина символа в пикселях(5 пикселей + 1 пиксель справа)
	#define height (8+2) // высота символа в пикселях(8 пикселей + 2 пикселя снизу)

	uint8_t byte, mask, i, n;
	uint16_t colors[width*height];


	//тут читаю побайтно. Каждый байт обрабатываю
	//и заполняю массив (0, 5, 10, ...), (1, 6, 11, ...)
	for (n = 0; n < 5; n++){
		mask = 1;
		byte = ASCII[ 5*ch + n ]; //каждый символ в ASCII состоит из 5 байт
		for ( i = 0; i < 8; i++){

			if ( (byte & mask) == mask ){
				colors[i*width + n] = foreground;
			} else {
				colors[i*width + n] = background;
			}
			mask = mask << 1;


		}

	}
	// заполнение отступа справа
	for (n = 5; n < width; n++){
		for ( i = 0; i < height; i++){
			colors[i*width + n] = background;
		}
	}
	//заполнение отступа снизу
	for ( i = 8; i < height; i++){
		for (n = 0; n < width; n++){
				colors[i*width + n] = background;
			}
	}

	ST7735_setAddrWindow(curX_PosChar, curY_PosChar, curX_PosChar + width - 1, curY_PosChar + height - 1);
	LcdWrite16(LCD_D , colors , width*height); // вывод символа (width х height) за раз

	if ( ST7735_width_curr - curX_PosChar - width >= width  )
		curX_PosChar = curX_PosChar + width;
	else{
		curX_PosChar = 0;

		if ( ST7735_height_curr - curY_PosChar - height >= height  )
			curY_PosChar = curY_PosChar + height;
		else
			curY_PosChar = 0;
	}

	//curY_PosChar = curY_PosChar + height;
}

void fillRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color){
	uint8_t x, y;

	ST7735_setAddrWindow(x1, y1, x2, y2);

	// вместо LcdWrite16(LCD_D , &color , 1); , там каждый раз устанавливаются CS, dc

		GPIO_WriteBit(LCD_PORT, GPIO_PIN_DC, LCD_D); //1 = data, 0 = control
		GPIO_ResetBits(LCD_PORT, GPIO_PIN_SCE);


		for ( x = x1; x <= x2; x++ ) {
			for ( y = y1; y <= y2; y++ ) {
				spiReadWrite16(SPILCD, 0, &color, 1, LCDSPEED);
			}
		}

		GPIO_SetBits(LCD_PORT, GPIO_PIN_SCE);

}

void lcd_printPixelLine(uint8_t y, uint16_t * colors, uint8_t n){
	uint8_t i;

		ST7735_setAddrWindow(0, y, ST7735_width_curr-1, y);

		GPIO_WriteBit(LCD_PORT, GPIO_PIN_DC, LCD_D); //1 = data, 0 = control
		GPIO_ResetBits(LCD_PORT, GPIO_PIN_SCE);

		spiReadWrite16(SPILCD, 0, colors, n, LCDSPEED);

		GPIO_SetBits(LCD_PORT, GPIO_PIN_SCE);
}

// (y1 - y2)x + (x2 - x1)y + (x1y2 - x2y1) = 0     ==    Ax + By + C = 0
void DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color){

	int16_t A, B, C, y, x, cx1, cx2;

	A = y1 - y2;
	B = x2 - x1;
	C = x1*y2 - x2*y1;

	if ( x1 < x2 ) {
		cx1 = x1;
		cx2 = x2;
	} else {
		cx1 = x2;
		cx2 = x1;
	}

	for ( x = cx1; x <= cx2; x++ ){
		y = ( - C - A * x ) / B;

		ST7735_setAddrWindow(x, y, x, y);
		ST7735_pushColor(&color, 1);
	}

}

// алгоритм Брезерхэма
void DrawLineBresenham(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color) {
    const int16_t deltaX = abs(x2 - x1);
    const int16_t deltaY = abs(y2 - y1);
    const int16_t signX = x1 < x2 ? 1 : -1;
    const int16_t signY = y1 < y2 ? 1 : -1;
    //
    int error = deltaX - deltaY;
    //
    //setPixel(x2, y2);
    ST7735_setAddrWindow(x2, y2, x2, y2);
    ST7735_pushColor(&color, 1);
    while(x1 != x2 || y1 != y2)
   {
        //setPixel(x1, y1);
        ST7735_setAddrWindow(x1, y1, x1, y1);
        ST7735_pushColor(&color, 1);
        const int error2 = error * 2;
        //
        if(error2 > -deltaY)
        {
            error -= deltaY;
            x1 += signX;
        }
        if(error2 < deltaX)
        {
            error += deltaX;
            y1 += signY;
        }
    }

}


void DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t thickness, uint16_t color){
	fillRect(x1, y1, x2, y1 + thickness -1, color);
	fillRect(x1, y2 - thickness +1, x2, y2, color);
	fillRect(x1, y1, x1 + thickness -1, y2, color);
	fillRect(x2 - thickness +1, y1, x2, y2, color);
}


// x = r*cos(&) + x0;
// y = r*sin(&) + y0;
/*void DrawCircle(uint8_t x0, uint8_t y0, uint8_t r, uint16_t color){


	uint16_t deg;
	double rad_k;
	int16_t x, y;

	rad_k = 4 * atan(1) / 180;

	for ( deg = 0; deg < 360; deg++ ){
		x = r * cos(deg * rad_k) + x0;
		y = r * sin(deg * rad_k) + y0;

		// если эта точка попадает на экран, то выводим её
		if( x >= 0 && y >= 0 && x < ST7735_width_curr && y < ST7735_height_curr ){
			ST7735_setAddrWindow(x, y, x, y);
			ST7735_pushColor(&color, 1);
		}
	}
}
*/

//окружность. алгоритм Брезерхэма. похоже на овал.

void DrawCircleBresenham(uint8_t x0, uint8_t y0, uint8_t r, uint16_t color){

		int16_t x = 0;
		int16_t y = r;
		int16_t delta = 1 - 2 * r;
		int16_t error = 0;

		while( y >= 0 ) {
			//setPixel(x0 + x, y0 + y);
			ST7735_setAddrWindow(x0 + x, y0 + y, x0 + x, y0 + y);
			ST7735_pushColor(&color, 1);
			//setPixel(x0 + x, y0 - y);
			ST7735_setAddrWindow(x0 + x, y0 - y, x0 + x, y0 - y);
			ST7735_pushColor(&color, 1);
			//setPixel(x0 - x, y0 + y);
			ST7735_setAddrWindow(x0 - x, y0 + y, x0 - x, y0 + y);
			ST7735_pushColor(&color, 1);
			//setPixel(x0 - x, y0 - y);
			ST7735_setAddrWindow(x0 - x, y0 - y, x0 - x, y0 - y);
			ST7735_pushColor(&color, 1);
			error = 2 * (delta + y) - 1;
			if(delta < 0 && error <= 0) {
				++x;
				delta += 2 * x + 1;
				continue;
			}
			error = 2 * (delta - x) - 1;
			if(delta > 0 && error > 0) {
				--y;
				delta += 1 - 2 * y;
				continue;
			}
			++x;
			delta += 2 * (x - y);
			--y;
		}
/////////////// получается то же самое ///////////////////////////
/*		int16_t f = 1 - r;
		int16_t ddF_x = 1;
		int16_t ddF_y = -2 * r;
		int16_t x = 0;
		int16_t y = r;

		ST7735_setAddrWindow(x0  , y0+r, x0  , y0+r);
		ST7735_pushColor(&color, 1);
		ST7735_setAddrWindow(x0  , y0-r, x0  , y0-r);
		ST7735_pushColor(&color, 1);
		ST7735_setAddrWindow(x0+r, y0, x0+r, y0);
		ST7735_pushColor(&color, 1);
		ST7735_setAddrWindow(x0-r, y0, x0-r, y0);
		ST7735_pushColor(&color, 1);

		while (x<y) {
			if (f >= 0) {
				y--;
				ddF_y += 2;
				f += ddF_y;
			}
			x++;
			ddF_x += 2;
			f += ddF_x;


			ST7735_setAddrWindow(x0 + x, y0 + y, x0 + x, y0 + y);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 - x, y0 + y, x0 - x, y0 + y);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 + x, y0 - y, x0 + x, y0 - y);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 - x, y0 - y, x0 - x, y0 - y);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 + y, y0 + x, x0 + y, y0 + x);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 - y, y0 + x, x0 - y, y0 + x);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 + y, y0 - x, x0 + y, y0 - x);
			ST7735_pushColor(&color, 1);
			ST7735_setAddrWindow(x0 - y, y0 - x, x0 - y, y0 - x);
			ST7735_pushColor(&color, 1);


			//ST7735_drawPixel(x0 + x, y0 + y, color);
			//ST7735_drawPixel(x0 - x, y0 + y, color);
			//ST7735_drawPixel(x0 + x, y0 - y, color);
			//ST7735_drawPixel(x0 - x, y0 - y, color);
			//ST7735_drawPixel(x0 + y, y0 + x, color);
			//ST7735_drawPixel(x0 - y, y0 + x, color);
			//ST7735_drawPixel(x0 + y, y0 - x, color);
			//ST7735_drawPixel(x0 - y, y0 - x, color);
		}
*/
}

100

Комментарии




information