PROGCONT.RU

Форма входа







Регистрация Вход/

Пример Пример Пример


STM8S выводим информацию и управляем контролером с помощью модуля на чипе TM1638 или как написать собственный драйвер.

Ссылка на видео в YouTube Как то в далекой галактике!
 Короче решил я сконструировать частотный преобразователь для асинхронного трехфазного двигателя на контролере stm8s903k3 и само собой возник вопрос как им управлять. Делать самому индикацию и выводить кнопки управления как то не хотелось, так как пришлось бы нагрузить этой работой контролер, задействовать много ног у него, плюс дополнительные компоненты, пайка деталей.

нет рисунка И тут конечно случайно наткнулся на данный модуль на чипе TM1638, причем порадовала цена около 90 руб на любимом AliExpress. Что хорошего у этой платы: 8 цифровых индикатора, 8 дополнительных светодиода, восемь кнопок управления и все это подключается к контролеру через три вывода(STB, CLK, DIO). Обмен информации происходит по SPI причем для передачи данных модулю и получение от него состояния кнопок происходит по двунаправленной линии DIO.
 Ниже схема как у меня подключен модуль к контролеру, все по datasheet единственное вывод модуля STB можно подключить к любому свободному выводу контролера.

нет рисунка

 Модуль готов к работе сразу после его включения, особых действий для инициализации делать не нужно. Теперь как модуль принимает команды, данные и как они должны отправляться.

нет рисунка

 На картинке мы видим, что по выводу CLK происходит тактирование, по DIO принимает и отправляет данные тут все стандартно, а вот STB предназначен для стробирования команд то есть когда происходит спад напряжения модуль понимает что должна прийти команда, а за ней могут идти только данные. Для другой команды придется опять поднять напряжение на выводе STB и опять его опустить как на картинке выше, при высоком состоянии вывода модуль не воспринимает команды и данные только в низком состоянии.

 Теперь о командах, у модуля имеется три вида команд: управление данными(записываем данные в модуль или сканируем кнопки), установка адреса для записи данных(устанавливаем адрес с которого будем менять данные или в который запишем новые) и управление самим модулем(включить, выключить и яркость индикации).
 Описание команд, смотрите ниже.

нет рисунканет рисунканет рисунка

нет рисунка Передача данных происходит после команды установившей адрес, четные адреса для символов и нечетные для управления светодиодом(8 бит для символа и 8 бит для светодиода).
 Формировать символы мы будем по схеме с права, вывод SEG1 соответствует элементу а который будет являться младшим битом(bit0) данных, записав туда единицу мы его зажжем, элемент b это bit1 и так далее. Например что бы отобразить ноль, байт данных должен быть b00111111(0x3f).
Управлять светодиодом проще надо записать в байт соответствующего адреса, в бит 0 (bit0) единицу зажигаем, погасить ноль.
 Ниже схема как будет выглядеть общение контролера с модулем.

нет рисунка

нет рисунка Программа для контролера работает следующим образом, после старта загораются все светодиоды кроме символьных, нажимаем кнопку и напротив загорается символ U, светодиод гаснет.
 Тут я отмечу три основные функции: send_command() которая отсылает команды, scan_button() возвращает 1байт результат нажатий(1бит первая кнопка, 2бит вторая и т.д), send_data() получает на вход 16байтный массив данных и байт сканирования кнопок, чтобы зажечь нужный символ и погасить светодиод.
 Ниже рабочий код под 16МГц внешний кварц, в настройке SPI тактирование передачи данных равна f MASTER /16(1МГц), пробовал f MASTER /8(2МГц) тоже стабильно работало.

#include "stm8s.h"

#define display_on 143
#define auto_inc_adres 64
#define set_adres_0 192
#define scan_button_press 66

void send_command(uint8_t com);
void send_data(uint8_t *send_data_display, uint8_t scan);
uint8_t scan_button(void);

 int main( void ){
//Включаем тактирование от внешнего источника, кварц 16МГц
   CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE,    CLK_CURRENTCLOCKSTATE_ENABLE);
   CLK_HSICmd(DISABLE);
   CLK_LSICmd(DISABLE);
//Настраиваем порты для SPI
   GPIO_Init(GPIOC,GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST);
   GPIO_Init(GPIOC,GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST);
//Настраиваем SPI и включаем
   SPI_Init( SPI_FIRSTBIT_LSB, SPI_BAUDRATEPRESCALER_16, SPI_MODE_MASTER,    SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_1LINE_TX,    SPI_NSS_SOFT, 0x07);
   SPI_Cmd(ENABLE);
//Массив для отправки данных
   uint8_t send_data_display[16];
//Включаем модуль и устанавливаем максимальную яркость
   send_command(display_on);
//Задаем автоматический инкремент адреса для данных
   send_command(auto_inc_adres);

      while(1){
//Опрашиваем модуль на нажатие кнопок и отправляем данные для отображения
      send_data(send_data_display, scan_button());
      }
 }

//Функция для отправки команды
void send_command(uint8_t com){
   GPIO_WriteLow(GPIOC, GPIO_PIN_4);
   SPI_SendData(com);
   while( (SPI->SR & SPI_FLAG_BSY) );
   GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
}

//Функция для опроса кнопок
uint8_t scan_button(void){
   uint8_t scan_result;
   GPIO_WriteLow(GPIOC, GPIO_PIN_4);
   SPI_SendData(scan_button_press);
   while( (SPI->SR & SPI_FLAG_BSY) );

//Перенастраиваем SPI на прием данных, принимаем 4байта и сокращаем их до 1байта
   SPI_BiDirectionalLineConfig(SPI_DIRECTION_RX);

   while( !(SPI->SR & SPI_FLAG_RXNE) );
   scan_result=SPI->DR;
   while( !(SPI->SR & SPI_FLAG_RXNE) );
   scan_result|=(SPI->DR<<1);
   while( !(SPI->SR & SPI_FLAG_RXNE) );
   scan_result|=(SPI->DR<<2);
   while( !(SPI->SR & SPI_FLAG_RXNE) );
   scan_result|=(SPI->DR<<3);
   GPIO_WriteHigh(GPIOC, GPIO_PIN_4);

//Перенастраиваем SPI на передачу данных
   SPI_BiDirectionalLineConfig(SPI_DIRECTION_TX);

   return scan_result;
}

//Функция для отправки данных
void send_data(uint8_t *send_data_display, uint8_t scan){
   uint8_t shift=1;
   for(uint8_t i=0;i<16;i+=2){
   if(shift & scan){send_data_display[i]=62;}
   else{send_data_display[i]=0;}
   shift<<=1;
   }
   shift=1;
   for(uint8_t i=1;i<16;i+=2){
   if(shift & scan){send_data_display[i]=0;}
   else{send_data_display[i]=1;}
   shift<<=1;
   }
   GPIO_WriteLow(GPIOC, GPIO_PIN_4);
   SPI_SendData(set_adres_0);
   while( (SPI->SR & SPI_FLAG_BSY) );
   for( uint8_t i=0;i<16;i++){
   SPI_SendData(send_data_display[i]);
   while( !(SPI->SR & SPI_FLAG_TXE) );
   }
   while( (SPI->SR & SPI_FLAG_BSY) );
   GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1){}
}
#endif

 Я надеюсь что помог вам научится управлять TM1638 или в написании собственного драйвера.


Комментарии  Только зарегистрированные пользователи могут оставлять комментарии!

NOPivnevnikolay   2018-02-12 14:52:18
Немного непонятен сам процесс настройки SPI SPI_Init( SPI_FIRSTBIT_LSB, SPI_BAUDRATEPRESCALER_16, SPI_MODE_MASTER, SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_1LINE_TX, SPI_NSS_SOFT, 0x07); SPI_FIRSTBIT_LSB->устанавливаем порядок следования бит(первым вставляется младший или старший бит). SPI_BAUDRATEPRESCALER_16->скорость SPI. SPI_MODE_MASTER ->мастер конфигурация. SPI_CLOCKPOLARITY_LOW->SPI_CLOCKPHASE_1EDGE->полярность и фаза тактового сигнала. SPI_DATADIRECTION_1LINE_TX->режим работы, передачи(поддерживаемый вид связи). SPI_NSS_SOFT->выбор режима работы мастера программный или аппаратный (дословный перевод из SPL управление ведомым программным обеспечением отключено соответственно SPI_NSS_HARD->разрешено)??? и вот это вообще непонятно в сети ничего нет uint8_t CRCPolynominal??? вроде как это расчёт контрольной суммы причём он должен быть настроен, единственное что удалось найти CRC Polynominal register что это регистр содержит значение полинома для вычесления контрольной суммы и по умолчанию его значение должно быть(0x07). Но в сети есть примеры где значение равно 0x00.

NOPivnevnikolay   2018-02-12 14:53:58
Заранее Спасибо за ответ!

NOPivnevnikolay   2018-02-12 16:29:44
SPI_NSS это вывод микроконтроллера в моём случае это PE5(STM8S105K4T6) чтоб его задействовать мне надо указать SPI_NSS_HARD, и вызвать SPI_NSSInternalSoftwareCmd(ENABLE) и управление данным выводом будет реализовано программно?

NOteseiaaw   2018-02-15 19:52:46
NSS используется только для SLAVE режима, программно вы должны установить бит в специальный(SPI_CR2 SSI) регистр иначе используется вывод, в CRCPolynomial можете писать любое число если не используете подсчет контрольной суммы.