Инициализация SPI в студии Atmel - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь использовать мой дисплей Micro OLED Sparkfun (вот таблица введите описание ссылки здесь ), но у меня проблема с кодом.Может быть, проблема в коде, потому что я работаю в первый раз с SPI в Atmel, так что если кто-то будет так любезен и проверьте его, дайте мне несколько советов о том, что я буду так благодарен.

РЕДАКТИРОВАТЬ: Вот изменилоськод и изображение проводов дисплея

#define F_CPU 16000000
 #include <avr/io.h>
 #include <util/delay.h>
 #define SCK DDB5
 #define SDIN DDB3
 #define D_C DDB0
 #define CS DDB2
 #define RST DDB1

 void SPI_MasterInit(void)
 {
     /* Set MOSI and SCK output, all others input */
     DDRB = (1<<SCK)|(1<<SDIN)|(1<<D_C)|(1<<CS)|(1<<RST);
     /* Enable SPI, Master, set clock rate fck/16 */
     PORTB |= (1<<CS);
     PORTB |= (1<<D_C);
     SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<DORD);
 }
 void SPI_MasterTransmit_Command(int cCommand)
 {
     PORTB &= ~(1<<CS);
     PORTB &= ~(1<<D_C);
     _delay_ms(200);
     /* Start transmission */
     SPDR = cCommand;
     /* set dc and cs low to send command */
     /* Wait for transmission complete */
     while(!(SPSR & (1<<SPIF)));
     /* set dc cs high again */
     PORTB |= (1<<CS);
     PORTB |= (1<<D_C);


 }

 void Display_ON(void)
 {
     PORTB &= ~(1<<RST);
     _delay_ms(50);
     PORTB |= (1<<RST);
     _delay_ms(50);
     PORTB &= ~(1<<RST);
     _delay_ms(50);
     SPI_MasterTransmit_Command(0xAF);
     _delay_ms(200);
 }

 int main(void)
 {
     SPI_MasterInit();
     Display_ON();
     SPI_MasterTransmit_Command(0xA5);

 }

enter image description here

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

First. Когда вы используете SPI на AVR ATmega в режиме master, вывод SS, хотя он не используется напрямую модулем SPI, должен быть всегда сконфигурированв противном случае высокий уровень на выводе переключит модуль SPI в подчиненный режим.Другими словами, если вы используете, например, ATmega328 (P), PB2 должен быть настроен как выход (бит DD2 в DDRB должен быть установлен).Рекомендуется подключить CS # SSD1306 к этому выводу.

Second .При подключении SSD1306 необходимо подключить 4 линии (см. Стр. 17 таблицы ): 1) SCLK - последовательные часы - подключите его к выводу SCK порта SPI (например, PB5 для ATmega328) 2)SDAT - последовательные данные - подключите его к выводу MOSI (PB3) 3) CS # - выбор микросхемы - подключите его к выводу SS (PB2) 4) D / # C - выбор данных / команды - подключите его к любому свободному выводу (как я полагаю, вы подключили его к PB0) Также модули могут иметь вход RESET, я думаю, что он подключен к PB1.

Итак, отправка байта данных или команды на SSD1306 должна выглядеть следующим образом:

PORTB &= ~(1 << CS); // pulling the CS# line low
PORTB |= (1 << D_C); // high for DATA
or
PORTB &= ~(1 << D_C); // low for COMMAND
SPDR = cData; // transmit the byte
while(!(SPSR & (1<<SPIF))) {} // wait the transmission to complete
PORTB |= (1 << CS); // pull the CS# line back high

CS # можно удерживать на низком уровне с помощью нескольких команд, не поднимаясь вверх.Это помогает определить ребра команды.

Третий .Команда 0xAF включит дисплей, но, вероятно, он ничего не покажет, потому что в нем нет данных, поэтому вы можете не видеть никакой разницы.Попытайтесь отправить команду 0xA5 сразу после этого, она осветит все пиксели - только для целей тестирования.

UPD Кроме того, там вы должны включить зарядный насос DC-DC(см. примечание по применению, стр. 62 в конце таблицы ).Это делается последовательностью из двух командных байтов 0x8D 0x14.Отправьте его перед включением дисплея (т.е. до 0xAF)

0 голосов
/ 22 сентября 2018

К сожалению, вы не указали точный мкК, который используете.Я просто использовал ATMEGA32 в качестве ссылки.Надеемся, что ваш AVR имеет такую ​​же конфигурацию.

ATMEGA32 также имеет интерфейс SPI на порту B. Вы полагаетесь на значение сброса регистра DDRB (которое равно нулю).Было бы неплохо явно установить все желаемые значения для вашей конфигурации выводов.Из таблицы данных ATMEGA кажется, что вы неправильно инициализировали контакты.Только PB7 и PB5 интерфейса SPI должны быть настроены на вывод.В вашей инициализации вы устанавливаете PB4, PB6 и PB7 для вывода.Вы смешали MISO и MOSI .

Вот моя процедура инициализации:

/* 
SPI pin configuration:
PB7: SCK         Output
PB6: MISO        Input
PB5: MOSI        Output
PB4: Chip select Output
*/
void SPI_MasterInit(void){
  DDRB = 0x00;
  DDRB |= ((1 << DDB2) | (1 << DDB5) | (1 << DDB7));
  PORTB |= (1<<PB2);
  /* Enable SPI, Master, set clock rate fck/16 */
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

Вам также необходимо проверить следующее:

  • Поддерживает ли дисплей выбранную вами частоту SPI?
  • Каким должно быть состояние SCK во время IDLE?
  • Когда следует выбирать данные SPI?Во время нарастания или спада SCK.
  • Установлена ​​ли CS в соответствии с временной диаграммой в спецификации OLED-дисплея?

Если вы позаботились обо всех этих вещах,пожалуйста, вернитесь с коротким отзывом.Я надеюсь, что этот ответ даст вам некоторые рекомендации, как действовать.

...