AVR для начинающих. Урок 13.SPI.Функции.

Автор: | 04.10.2016

Здравствуйте!

В прошлом уроке мы рассмотрели интерфейс SPI и его регистры. Сегодня, мы напишем несколько функций для передачи данных при помощи SPI.

Работать будем с микроконтроллером AtMega8. SPI микроконтроллера AtMega8 работает на следующих выводах:

Вывод

Функция

PB2

SS

PB3

MOSI

PB4

MISO

PB5

SCK

 

Итак, приступим.

Инициализация SPI.

Master

Скорость передачи Fosc/8,режим работы Master.

Slave

Скорость передачи Fosc/8,режим работы Slave, прерывание по окончанию приема\передачи данных включено.

Читайте также  AVR для начинающих.Урок 0.Знакомство с микроконтроллерами.

Передача данных

Обмен байтами

Отправить строку

 

Прием байта в прерывании

Для включения прерывания необходимо установить в “1” бит SPIE регистра SPCR,а так же разрешить прерывания глобально командой sei . Подробнее о прерываниях !ЗДЕСЬ!.

Для примера передадим байт с одного контроллера AtMega8 на другой микроконтроллер AtMega8 по SPI, и выведем принятый байт на LCD. О подключении LCD к микроконтроллеру читайте здесь.

Читайте также  Программаторы AVR.

Соберем в Proteus следующую схему. О том как создать проект в Proteus смотрите здесь.

Напишем 2 прошивки, для ведущего и ведомого.

Прошивка ведущего:

 

Прошивка ведомого:

 

Я специально убрал код вывода символа на дисплей. Напишите его самостоятельно, при необходимости.

В результате запуска симуляции видим:

Отправленный байт успешно принят и выведен на экран.

Спасибо за внимание! Вопросы оставляйте в комментариях.

Другие уроки цикла.


Любое копирование, воспроизведение, цитирование материала, или его частей разрешено только с письменного согласия администрации MKPROG.RU. Незаконное копирование, цитирование, воспроизведение преследуется по закону!

AVR для начинающих. Урок 13.SPI.Функции.: 8 комментариев

  1. Azerhud

    Здравствуйте. Не получается вывести символ на ЖК. Что я делаю не так?
    ISR(SPI_STC_vect)
    {
    lcd_write_character_4d(SPDR);
    return ;
    }

    int main(void)
    {
    sei();
    data=SPI_Init_Slave();
    lcd_init_4d();

    lcd_write_string_4d(SPI_Init_Slave());
    lcd_write_instruction_4d(lcd_SetCursor | lcd_LineTwo);

    while (1)
    {
    }
    }

    1. DamiKK Автор записи

      Здравствуйте!
      А просто произвольный текст выводится?Попробуйте вывести допустим Hello World.

  2. Azerhud

    Да. Произвольный текст выводится.
    int main(void)
    {
    sei();
    SPI_Init_Slave();
    lcd_init_4d();

    lcd_write_string_4d(«Hello World»);
    lcd_write_instruction_4d(lcd_SetCursor | lcd_LineTwo);
    while(1)
    {

    }
    }

      1. Azerhud

        Нужно было добавить lcd_init_4d(); перед строчкой lcd_write_character_4d(SPDR);

        ISR(SPI_STC_vect)
        {
        lcd_init_4d();
        lcd_write_character_4d(SPDR);
        return ;
        }

  3. Azerhud

    Не подскажите код для отправки строки из двух-трёх букв?

    1. DamiKK Автор записи

      Передавайте строку по байтам. Код есть в статье.

  4. Azerhud

    Здравствуйте.
    Пытаюсь передать строку. Но у меня почему то появляется только первая буква. Подскажите пожалуйста, где ошибка?
    Код мастера:
    #define F_CPU 8000000UL

    #include
    #include

    void SPI_Init(void)
    {
    DDRB |=(1<<PB2)|(1<<PB3)|(1<<PB5); //Настроить выводы MOSI,SS,SCK на выход
    PORTB|=(1<<PB2); //Установить "1" на линии SS

    SPCR = 0; //Обнулить регистр SPCR
    SPSR = 0; //Обнулить регистр SPSR

    SPCR |= (1<<MSTR)|(1<<SPR0); //Режим мастер, F=Fosc/16
    SPSR |=(1<<SPI2X); //F=Fosc/8

    SPCR |=(1<<SPE);//Включить SPI
    }

    void SPI_Send_String ( unsigned char str[])
    {
    PORTB &=~(1<<PB2); //Установить "0" на линии SS
    unsigned char i=0;

    while (str[i]!='\0') // Пока текущий символ не конец строки
    {
    SPDR = str[i]; //Отправить символ(байт)
    while(!(SPSR&(1<<SPIF))) ; //Дождаться окончания передачи

    i++; //Перейти к следующему
    }

    PORTB |=(1<<PB2); //Установить "1" на линии SS
    }

    int main(void)
    {
    SPI_Init();
    SPI_Send_String("MKPROG.RU");

    while(1)
    {

    };
    }

    Код ведомого:
    #define F_CPU 8000000UL

    #include
    #include
    #include
    #include
    #include
    void SPI_Init_Slave(void)
    {
    DDRB&= ~(1<<PB2) | ~(1<<PB3) |~(1<<PB5);
    DDRB|=(1<<PB4);

    SPCR=0;
    SPSR=0;

    SPCR |= (1<<SPR0)|(1<<SPIE);
    SPSR |=(1<<SPI2X);

    SPCR |=(1<<SPE);
    }

    ISR(SPI_STC_vect)
    {
    char t=SPDR;
    lcd_init_4d();
    lcd_write_character_4d(t);

    if(t=='G')
    {
    PORTC=0x01;
    }
    return ;
    }

    int main(void)
    {
    DDRC=0x01;
    PORTC=0x00;
    sei();
    SPI_Init_Slave();
    while(1)
    {

    }
    }

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *