SPL: работаем с SPI

     Краткое описание: Для работы с этим примером необходимы плата расширения 1 и Индикатор (t°C). Подключаем индикационную плату Индикатор (t°C) к плате CodeIN через плату расширения 1 рисунок 1. 

     Задача: Требуется написать с использованием библиотеки StdPeriph код. Программа должна демонстрировать работу с индикационной платой по SPI интерфейсу. Первый пример: реализует счетчик от 0 до 999 с обнулением при достижении максимального значения. Инкрементирование счетчика происходит в главном цикле программы. Второй пример: должен реализовать счетчик нажатия на пользовательскую кнопку. 

Рисунок 1

#include "stm32f30x.h"
#include "stm32f30x_gpio.h"
#include "stm32f30x_rcc.h"
#include "stm32f30x_spi.h"
#include "stm32f30x_syscfg.h"

#define Zero 63 //Соответствует цифре <0> на индикаторе
#define One 6 // Соответствует цифре <1> на индикаторе
#define Two 91 //Соответствует цифре <2> на индикаторе
#define Three 79 //Соответствует цифре <3> на индикаторе
#define Four 102 //Соответствует цифре <4> на индикаторе
#define Five 109 //Соответствует цифре <5> на индикаторе
#define Six 125 //Соответствует цифре <6> на индикаторе
#define Seven 7 //Соответствует цифре <7> на индикаторе
#define Eight 127 //Соответствует цифре <8> на индикаторе
#define Nine 111 //Соответствует цифре <9> на индикаторе
#define Point 128 // Соответствует точке на индикаторе

#define Led_ALL_Good 1 //Соответствует зеленому цвету
#define Led_Warning 2 //Соответствует красному цвету

int Indikator_1 = Zero; //Присваиваем переменной индикатора 1 значение 0
int Indikator_2 = Zero; //Присваиваем переменной индикатора 2 значение 0
int Indikator_3 = Zero; //Присваиваем переменной индикатора 3 значение 0

int Led_conf = Led_ALL_Good; //Присваиваем переменной светодиода значение соответствующее зеленному цвету

GPIO_InitTypeDef gpio; //Объявляем переменную gpio типа GPIO_InitTypeDef
SPI_InitTypeDef spi; //Объявляем переменную spi типа SPI_InitTypeDef

int k = 0; //Переменная для условной операции изменения значения индикатора 1
int m = 0; //Переменная для условной операции изменения значения индикатора 2
int n = 0; //Переменная для условной операции изменения значения индикатора 3

int flag; //Для второго примера: переменная используется для условия однократного инкремента переменной индикатора при однократном нажатии кнопки                                                                                               

void initAll()
{
    RCC_HSICmd(ENABLE); //Включаем тактирование от внутреннего источника
    RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); //Подаем тактовый сигнал на системную шину

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //Включаем тактирование SPI1
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //Включаем тактирование порта A
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //Включаем тактирование порта B

    gpio.GPIO_Mode = GPIO_Mode_OUT; //Выбираем режим работы пинов: ВЫХОД
    gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //Выбираем пин PB0( <LE> нужен для вывода данных на индикаторы после загрузки посылки                                                                                                                  // в микросхему MBI), пин PB1 <nOE> Для включения микросхемы MBI
    GPIO_Init(GPIOB, &gpio); //Инициализируем структуру с настройками

    //Для второго примера
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); //Включаем тактирование соответствующих портов
    gpio.GPIO_Mode = GPIO_Mode_IN; //Выбираем режим работы пина: ВХОД
    gpio.GPIO_Pin = GPIO_Pin_0; //Выбираем нужны пин
    GPIO_Init(GPIOC, &gpio); //Инициализируем структуру с настройками

    //Настраиваем пины SPI1 для работы в режиме альтернативной функции
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_5); //Будет использоваться как SCK
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_5); //Будет использоваться как SDO
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_5); //Будет использоваться как SDI

    gpio.GPIO_Mode = GPIO_Mode_AF; //Выбираем режим работы пинов: Альтернативная функция
    gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; //Выбираем нужные пины
    GPIO_Init(GPIOA, &gpio); //Инициализируем структуру с настройками

    //Заполняем структуру с параметрами SPI модуля
    spi.SPI_Direction = SPI_Direction_1Line_Tx; //Полный дуплекс
    spi.SPI_DataSize = SPI_DataSize_8b; //Передаем по 8 бит
    spi.SPI_CPOL = SPI_CPOL_High; //Полярность и
    spi.SPI_CPHA = SPI_CPHA_2Edge; //Фаза тактового сигнала
    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_Init(SPI1, &spi); //Настраиваем SPI1
    SPI_Cmd(SPI1, ENABLE); // Включаем модуль SPI1

    //Поскольку сигнал NSS контролируется программно, установим его в единицу
    //Если сбросить его в ноль, то наш SPI модуль подумает, что
    //у нас мультимастерная топология и его лишили полномочий мастера.
    SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
}

int main()

{

    initAll(); //Вызываем функцию инициализации
    GPIO_ResetBits(GPIOB, GPIO_Pin_1); //Включаем микросхему MBI (для этого подтягиваем ножку PB1 земле)

    while (1)

    {

        //Условия переключения значений индикатора 1
        if (k == 0) {
            Indikator_1 = Zero;
        }
        if (k == 1) {
            Indikator_1 = One;
        }
        if (k == 2) {
            Indikator_1 = Two;
        }
        if (k == 3) {
            Indikator_1 = Three;
        }
        if (k == 4) {
            Indikator_1 = Four;
        }
        if (k == 5) {
            Indikator_1 = Five;
        }
        if (k == 6) {
            Indikator_1 = Six;
        }
        if (k == 7) {
            Indikator_1 = Seven;
        }
        if (k == 8) {
            Indikator_1 = Eight;
        }
        if (k == 9) {
            Indikator_1 = Nine;
        }

        //Условия переключения значений индикатора 2
        if (m == 0) {
            Indikator_2 = Zero;
        }
        if (m == 1) {
            Indikator_2 = One;
        }
        if (m == 2) {
            Indikator_2 = Two;
        }
        if (m == 3) {
            Indikator_2 = Three;
        }
        if (m == 4) {
            Indikator_2 = Four;
        }
        if (m == 5) {
            Indikator_2 = Five;
        }
        if (m == 6) {
            Indikator_2 = Six;
        }
        if (m == 7) {
            Indikator_2 = Seven;
        }
        if (m == 8) {
            Indikator_2 = Eight;
        }
        if (m == 9) {
            Indikator_2 = Nine;
        }

        //Условия переключения значений индикатора 3
        if (n == 0) {
            Indikator_3 = Zero;
        }
        if (n == 1) {
            Indikator_3 = One;
        }
        if (n == 2) {
            Indikator_3 = Two;
        }
        if (n == 3) {
            Indikator_3 = Three;
        }
        if (n == 4) {
            Indikator_3 = Four;
        }
        if (n == 5) {
            Indikator_3 = Five;
        }
        if (n == 6) {
            Indikator_3 = Six;
        }
        if (n == 7) {
            Indikator_3 = Seven;
        }
        if (n == 8) {
            Indikator_3 = Eight;
        }
        if (n == 9) {
            Indikator_3 = Nine;
        }

        //Условия переключения цветов светодиода
        if (n == 0) Led_conf = Led_ALL_Good;
        if (n == 2) Led_conf = Led_Warning;

        GPIO_ResetBits(GPIOB, GPIO_Pin_0); //Сбрасываем LE

        SPI_SendData8(SPI1, Led_conf); //Передаем байт управляющий цветами светодиода
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //Передатчик занят? значит ничего не делаем

        SPI_SendData8(SPI1, Indikator_1); //Передаем байт управляющий первым индикатором
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //Передатчик занят? значит ничего не делаем

        SPI_SendData8(SPI1, Indikator_2); //Передаем байт управляющий вторым индикатором
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //Передатчик занят? значит ничего не делаем

        SPI_SendData8(SPI1, Indikator_3); //Передаем байт управляющий третьим индикатором
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); //Передатчик занят? значит ничего не делаем

        GPIO_SetBits(GPIOB, GPIO_Pin_0); //Устанавливаем LE для вывода переданных данных на индикаторы
        for (int i = 0; i < 30000; i++)
            i == 0; //Немного ждем прежде чем обновить данные

        //Пример 1

        k++; //Увеличиваем переменную значения 1-го индикатора на 1

        if (k == 10) //Если досчитали до 10 (1-й индикатор)
        {

            m++; //Увеличиваем переменную значения 2-го индикатора на 1
            k = 0; //Обнуляем переменную значения 1-го индикатора

            if (m == 10) //Если досчитали до 10 (2-й индикатор)
            {
                n++; //Увеличиваем переменную значения 3-го индикатора на 1
                m = 0; //Обнуляем переменную значения 2-го индикатора
                if (n == 10) //Если досчитали до 10 (3-й индикатор)
                {
                    n = 0; //Обнуляем переменную значения 3-го индикатора
                }
            }
        }

        //Пример 2

        /*if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 1 && flag==1) //Узнаем состояние входа PIN0 если кнопка нажата
     {
          k++; //Увеличиваем переменную значения 1-го индикатора на 1
          flag=0; //Сбрасываем флаг
     }
     if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0) //Если кнопка была отпущена
     {
          flag=1; //Взводим флаг
     }

     if (k==10) //Если досчитали до 10 (1-й индикатор)
     {
          m++; //Увеличиваем переменную значения 2-го индикатора на 1
          k=0; //Обнуляем переменную значения 1-го индикатора

          if (m==10) //Если досчитали до 10 (2-й индикатор)
          {
               n++; //Увеличиваем переменную значения 3-го индикатора на 1
               m=0; //Обнуляем переменную значения 2-го индикатора
               if (n==10) //Если досчитали до 10 (3-й индикатор)
               {
                    n=0; //Обнуляем переменную значения 3-го индикатора
               }
          }
     }*/
    }
}

     Скомпилируйте программу нажав кнопку Build, прошейте микроконтроллер, нажмите RESET. В первом примере счетчик будет увеличивать свое значение с очень небольшой задержкой. При достижении значения 999 счетчик будет обнуляться и считать заново. Закомментируйте первый пример и раскомментируйте второй, скомпилируйте и прошейте контроллер. Теперь при нажатии на пользовательскую кнопку значение счетчика будет увеличиваться на единицу. В обоих случаях если счетчик досчитает до 200, двухцветный светодиод на плате загорится красным цветом, и будет гореть до обнуления значения, после чего загорится зеленый светодиод, а красный погаснет. 

     ВНИМАНИЕ: Приведенный листинг кода не является единственной и оптимальной реализацией поставленной задачи. Пример опубликован с демонстрационной целью. Также автор во избежание переписывания чужих статей, пропускает теоретические основы необходимые для понимания примера, связывая это с тем что всю необходимую информацию можно найти в интернете.

Комментариев (0)

Написать комментарий

Имя *
E-mail
Введите комментарий *
Капча
24 + ? = 34