Есть у меня пару экранчиков с данным чипом.
По i2c подключился без проблем.
А вот с spi вышла засада. Вчера до полуночи пытался вдохнуть жизнь в экранчик (рабочий, на AVR работает без проблемм).
Совсем отчаялся, вытащил stlink из usb и пошел водички перед сном попить.
Пока ходил, пришла еще одна мысль, дай как еще попробую. Втыкаю программатор в юсб, а оно заработало!
Т.е. проблема номер раз - при перепрошивке, экран не поднимается, только при полном отключении питания.
Ну еще час потерянного сна и постоянное тыкание туда-сюда программатора.
Картинку выводит, но только в первый раз. Если в цикле, то картинка за пару секунд приходит в непотребный вид.
Дальше, все на картинках.
Вот так выглядит экран, если выводить один раз, а потом просто пустой цикл без обновления экрана. Ну и программатор передернуть, естественно.
А вот так, если обновлять одну и ту же картинку в цикле.
Все статьи, что нашел, прочитал, все попробовал. Но где-то у меня принципиальный косяк в понимании.
Не могу понять:
1. Почему не работает сразу после прошивки и надо передергивать питание?
2. Почему в цикле портится картинка.
Код прилагаю.
Спойлер
Код: Выделить всё
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_spi.h"
#define SSD1306_EXTERNALVCC 0x1
#define SSD1306_SWITCHCAPVCC 0x2
#define SSD1306_DEACTIVATE_SCROLL 0x2E
#define BLACK 0
#define WHITE 1
#define INVERSE 2
#define NONE 3
#define SSD1306_SETCONTRAST 0x81
#define SSD1306_DISPLAYALLON_RESUME 0xA4
#define SSD1306_DISPLAYALLON 0xA5
#define SSD1306_NORMALDISPLAY 0xA6
#define SSD1306_INVERTDISPLAY 0xA7
#define SSD1306_DISPLAYOFF 0xAE
#define SSD1306_DISPLAYON 0xAF
#define SSD1306_SETDISPLAYOFFSET 0xD3
#define SSD1306_SETCOMPINS 0xDA
#define SSD1306_SETVCOMDETECT 0xDB
#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
#define SSD1306_SETPRECHARGE 0xD9
#define SSD1306_SETMULTIPLEX 0xA8
#define SSD1306_SETLOWCOLUMN 0x00
#define SSD1306_SETHIGHCOLUMN 0x10
#define SSD1306_SETSTARTLINE 0x40
#define SSD1306_MEMORYMODE 0x20
#define SSD1306_COLUMNADDR 0x21
#define SSD1306_PAGEADDR 0x22
#define SSD1306_COMSCANINC 0xC0
#define SSD1306_COMSCANDEC 0xC8
#define SSD1306_SEGREMAP 0xA0
#define SSD1306_CHARGEPUMP 0x8D
#define SSD1306_EXTERNALVCC 0x1
#define SSD1306_SWITCHCAPVCC 0x2
static uint8_t buffer[64 * 128 / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//1....GND: Power ground
//2....VCC: 3.3V or 5V power supply
//3....D0: CLK Clock
//4....D1: MOSI data
//5....RST: Reset
//6....DC: data / command
//7....CS: Chip select signal
#define LED_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_13);
#define LED_ON GPIO_SetBits(GPIOC, GPIO_Pin_13);
void init_gpio()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
//светодиод (reset)
GPIO_InitTypeDef init;
init.GPIO_Mode = GPIO_Mode_Out_PP;
init.GPIO_Pin = GPIO_Pin_13;
init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &init);
//ноги SPI
init.GPIO_Mode = GPIO_Mode_AF_PP;
init.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOA, &init);
//нога для D/C (данные/команда)
init.GPIO_Mode = GPIO_Mode_Out_PP;
init.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &init);
}
void init_spi()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
SPI_InitTypeDef spi;
SPI_StructInit(&spi);
spi.SPI_Direction = SPI_Direction_1Line_Tx; //только на передачу, по одной линии
spi.SPI_DataSize = SPI_DataSize_8b;
spi.SPI_CPOL = SPI_CPOL_Low; //полярность
spi.SPI_CPHA = SPI_CPHA_1Edge; //и фаза тактового сигнала
spi.SPI_NSS = SPI_NSS_Soft; //NSS управлять программно
spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //предделитель SCK
spi.SPI_FirstBit = SPI_FirstBit_MSB; //первым идет старший бит
spi.SPI_Mode = SPI_Mode_Master; //режим
SPI_I2S_DeInit(SPI1);
SPI_Init(SPI1, &spi);
SPI_Cmd(SPI1, ENABLE);
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
}
// передача команды на дисплей
void spi1_CmdMode()
{
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // DC=0;
}
// передача данных на дисплей
void spi1_DataMode()
{
GPIO_SetBits(GPIOA, GPIO_Pin_0); // DC=1;
}
//послать байт
void spi1_SendByte(uint8_t sendData)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, sendData);
}
void delay(uint32_t c)
{
for(int i=0; i<c; i++);
}
int main(void)
{
init_gpio();
init_spi();
int i;
//ресет экрана
LED_ON
delay(1000);
LED_OFF
delay(10000);
LED_ON
spi1_CmdMode();
spi1_SendByte(0xAE); //display off
spi1_SendByte(0x20); //Set Memory Addressing Mode
spi1_SendByte(0x00); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
spi1_SendByte(0xB0); //Set Page Start Address for Page Addressing Mode,0-7
spi1_SendByte(0xC8); //Set COM Output Scan Direction
spi1_SendByte(0x00); //---set low column address
spi1_SendByte(0x10); //---set high column address
spi1_SendByte(0x40); //--set start line address
spi1_SendByte(0x81); //--set contrast control register
spi1_SendByte(0xFF);
spi1_SendByte(0xA1); //--set segment re-map 0 to 127
spi1_SendByte(0xA6); //--set normal display
spi1_SendByte(0xA8); //--set multiplex ratio(1 to 64)
spi1_SendByte(0x3F); //
spi1_SendByte(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
spi1_SendByte(0xD3); //-set display offset
spi1_SendByte(0x00); //-not offset
spi1_SendByte(0xD5); //--set display clock divide ratio/oscillator frequency
spi1_SendByte(0xF0); //--set divide ratio
spi1_SendByte(0xD9); //--set pre-charge period
spi1_SendByte(0x22); //
spi1_SendByte(0xDA); //--set com pins hardware configuration
spi1_SendByte(0x12);
spi1_SendByte(0xDB); //--set vcomh
spi1_SendByte(0x20); //0x20,0.77xVcc
spi1_SendByte(0x8D); //--set DC-DC enable
spi1_SendByte(0x14); //
spi1_SendByte(0xAF); //--turn on SSD1306 panel
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)!=RESET); // ждем пока данные передадутся до конца
spi1_SendByte(0x21);
spi1_SendByte(0);
spi1_SendByte(127);
spi1_SendByte(0x22);
spi1_SendByte(0);
spi1_SendByte(7);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)!=RESET); // ждем пока данные передадутся до конца
spi1_DataMode();
for(i=0; i<128*64/8; i++)
spi1_SendByte(buffer[i]);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)!=RESET); // ждем пока данные передадутся до конца
while(1)
{
spi1_CmdMode();
spi1_SendByte(0x21);
spi1_SendByte(0);
spi1_SendByte(127);
spi1_SendByte(0x22);
spi1_SendByte(0);
spi1_SendByte(7);
while (SPI_I2S_GetFlagStatus(SPI1, (1 << 7))!=RESET); // ждем пока данные передадутся до конца
//копируем буфер на экран
spi1_DataMode();
for(i=0; i<128*64/8; i++)
spi1_SendByte(buffer[i]);
while (SPI_I2S_GetFlagStatus(SPI1, (1 << 7))!=RESET); // ждем пока данные передадутся до конца
//for(i=0; i<100000; i++);
}
}
Если кто-то настолько крут, что мельком пробежавшись по коду, найдет ошибку, не сочтите за труд ткнуть носом.
Спасибо.
