Форум РадиоКот https://radiokot.ru/forum/ |
|
stm32 и подключение sdd1306 по SPI https://radiokot.ru/forum/viewtopic.php?f=59&t=146600 |
Страница 1 из 1 |
Автор: | aaleksander [ Пт июл 07, 2017 09:39:58 ] |
Заголовок сообщения: | stm32 и подключение sdd1306 по SPI |
Добрый день всем. Есть у меня пару экранчиков с данным чипом. По 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++); } } Если кто-то настолько крут, что мельком пробежавшись по коду, найдет ошибку, не сочтите за труд ткнуть носом. Спасибо. |
Автор: | Zhuk72 [ Пт июл 07, 2017 10:36:30 ] |
Заголовок сообщения: | Re: stm32 и подключение sdd1306 по SPI |
Код не смотрел, но на подобное наткнулся на прошлой неделе со 103С8 и дисплеем 5110. Мучился, ну никак не выводит инфо, и это при том, что на ПИКе я его инициализацию вылизал по полной. Утром включаю комп, втыкаю st-link, от которого питается плата с ЖКИ и с удивлением вижу свой текст, который накануне упорно пытался вывести. Причина в том, что после подачи питания на дисплей нужно провести его правильную инициализацию сразу. А в том случае, когда вы пару раз в процессе наладки обновляете прошивку, питание с дисплея не снимается, процедура инита проходит запоздало (от момента запитывания), вот он и молчит. Так что ставьте ключ на питание дисплея и включайте его из программы перед инициализацией. Либо, как я временно сделал (каюсь, неправильно это), подключил вывод питания на ногу МК. Т.е. он питается "единицей" с порта ![]() |
Автор: | aaleksander [ Пт июл 07, 2017 11:21:15 ] |
Заголовок сообщения: | Re: stm32 и подключение sdd1306 по SPI |
Zhuk72, ну это решение в лоб, оно же - костыль. Хотя право на жизнь имеет. Останавливает то, что этот же экран от аврки запускается на ура. Ну и второй вопрос остается: почему портится картинка при обновлении. На лицо косяк в логике. |
Автор: | Zhuk72 [ Пт июл 07, 2017 11:39:54 ] |
Заголовок сообщения: | Re: stm32 и подключение sdd1306 по SPI |
Я только на первый вопрос отвечал. А АВР же не питается от программатора, верно? Тут проблема в том, что схема запитывается от st-link и во время прошивки питание остается на дисплее, а время начала инициализации уже превысило какое-то паспортное. Костыль, я же не спорю. Но я был вдали от дома и лепить ключ на питание было не из чего. А сейчас некогда. На второй не отвечу, т.к. покупка такого ОЛЕДа только в планах. Добавлено after 3 minutes 23 seconds: Только сейчас обратил внимание на картинки. Нет времени смотреть код, но проверьте как обстоят дела с адресацией в этих дисплеях. Адрес автоматически инкрементируется, а в цикле у вас, вероятно, начальный адрес не задается. Вернее задается один раз где-то до начала цикла, потому и происходит смещение. Это просто предположение. |
Автор: | Зурбаган [ Пт июл 07, 2017 15:48:39 ] |
Заголовок сообщения: | Re: stm32 и подключение sdd1306 по SPI |
Код: init.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_5 | не вижу NSS, он же CS на стороне дисплея. Как он подключен? Его настоятельно рекомендуется подключать не к GND, а именно к управляемому с микроконтроллера выводу. Иначе, пока не инициализован SPI, на дисплей могут проникать шумовые данные от шины и портить весь старт дисплея. Скопировав весь ваш код и устранив указанное замечание - добавив программное переключение CS = 0 перед началом команд, либо поставив аппаратное управление SPI1->CR2 = SPI_CR2_SSOE и назначив PA4 на выход AF, теперь всё работает без сбоев: (у меня сине-желтый дисплей с двумя областями, поэтому видна ступенька) ![]() Сбои у вас были от наводок на CS дисплея из-за висящего в воздухе вывода. Попробуйте без исправления кода пальцем ткнуть в CS - у вас все полетит к чертям. ЗЫ. RESET дисплея у меня подключен к общему сбросу отладочной платы и отдельная команда сброса дисплея не используется ЗЫ-2. Каждый раз задавать начальные и конечные координаты окна вывода в этом конкретном случае - НЕ нужно. Дисплей работает по кругу, после последнего столбца последней страницы он автоматом переходит на первый. ЗЫ-3. После подачи питания дисплей может сколь угодно долго находиться в стендбае без инициализации, а инициализация и его включение может быть проведена в любое время, и после этого дисплей будет работать нормально. ЗЫ-4. Рекомендовано выдерживать некоторые задержки, в частности, после включения DC/DC-конвертера. В документации об этом сказано. 100 мс написано. Но на деле работает и с гораздо меньшей. After VCC become stable, send command AFh for display ON. SEG/COM will be ON after 100ms (tAF). ЗЫ-5. Чисто формально, буфер должен определяться не как [64 * 128 / 8], а как [128 * 64 / 8]. Хотя это чистая формальность, но смысл диаметрально противоположный - страниц в дисплее 64/8, а не 128/8. Впоследствии, это может запутать. |
Автор: | aaleksander [ Сб июл 08, 2017 05:41:51 ] |
Заголовок сообщения: | Re: stm32 и подключение sdd1306 по SPI |
Код: init.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_5 | не вижу NSS, он же CS на стороне дисплея. Как он подключен? Его настоятельно рекомендуется подключать не к GND, а именно к управляемому с микроконтроллера выводу. Иначе, пока не инициализован SPI, на дисплей могут проникать шумовые данные от шины и портить весь старт дисплея. Скопировав весь ваш код и устранив указанное замечание - добавив программное переключение CS = 0 перед началом команд, либо поставив аппаратное управление SPI1->CR2 = SPI_CR2_SSOE и назначив PA4 на выход AF, теперь всё работает без сбоев: Сбои у вас были от наводок на CS дисплея из-за висящего в воздухе вывода. Попробуйте без исправления кода пальцем ткнуть в CS - у вас все полетит к чертям. Блин, вот это опечатка ![]() Спасибо, все заработало. Но почему-то CS не хочет работать при Mode = GPIO_Mode_AF_PP: когда подношу палец к проводу, начинаются пляски. Поэтому настроил его отдельно на выход и сразу выставил в ноль. Теперь все работает стабильно. Огромное спасибо за помощь. Полностью рабочий код, если кому надо: СпойлерКод: #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "stm32f10x_spi.h" //подключение: //DO -> A5 //D1 -> A7 //res -> C13 //DC -> A0 //CS -> A4 #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[128*64/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 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 (MISO(A6) не используем) init.GPIO_Mode = GPIO_Mode_AF_PP; init.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; GPIO_Init(GPIOA, &init); //нога для D/C (данные/команда) и для выбора чипа (NSS, CS) init.GPIO_Mode = GPIO_Mode_Out_PP; init.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_4; 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); } #define LED_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_13); #define LED_ON GPIO_SetBits(GPIOC, GPIO_Pin_13); 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++); } void sdd_1306_init() { //ресет LED_ON delay(1000); LED_OFF delay(10000); LED_ON //spi1_SetCmdMode(); //режим командр GPIO_ResetBits(GPIOA, GPIO_Pin_0); // DC=0; 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 //адресация 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); // ждем пока данные передадутся до конца //переключаемся на данные, больше команд не будет GPIO_SetBits(GPIOA, GPIO_Pin_0); // DC=1; //spi1_SetDataMode(); } void display() { for(int i=0; i<128*64/8; i++) spi1_SendByte(buffer[i]); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)!=RESET); // ждем пока данные передадутся до конца } int main(void) { init_gpio(); init_spi(); sdd_1306_init(); display(); while(1) { } } |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |