Форум РадиоКот https://radiokot.ru/forum/ |
|
Работа с семисегментным дисплеем через TM1637 https://radiokot.ru/forum/viewtopic.php?f=61&t=155104 |
Страница 1 из 1 |
Автор: | isx [ Ср май 23, 2018 01:49:14 ] |
Заголовок сообщения: | Работа с семисегментным дисплеем через TM1637 |
Приветствую всех форумчан! Начал недавно разбираться с микросхемой на ТМ1637, но к успеху это не привело ![]() Суть в следующем: Для Ардуино есть готовые библиотеки, которые работают нормально, но мне нужно для STM32. В даташите есть пример кода для какого-то микроконтрроллера: СпойлерКод: # include <reg52.h> # include <intrins.h> / / Define port sbit clk = P1 ^ 2; sbit dio = P1 ^ 1; / / / ===================== void Delay_us (unsigned int i) // n us delay { for (; i> 0; i--) _nop_ (); } / / / ==================== void I2CStart (void) // 1637 start { clk = 1; dio = 1; Delay_us (2); dio = 0; } / / / ========= void I2Cask (void) // 1637 Answer { clk = 0; Delay_us (5); // After the falling edge of the eighth clock delay 5us, ACK signals the beginning of judgment while (dio); clk = 1; Delay_us (2); clk = 0; } / / / ==== void I2CStop (void) // 1637 Stop { clk = 0; Delay_us (2); dio = 0; Delay_us (2); clk = 1; Delay_us (2); dio = 1; } / / / ===== void I2CWrByte (unsigned char oneByte) // write a byte { unsigned char i; for (i = 0; i <8; i + +) { Clk = 0; if (oneByte & 0x01) // low front {dio = 1;} else {dio = 0;} Delay_us (3); oneByte = oneByte >> 1; clk = 1; Delay_us (3); } } / / / ---------- - unsigned char ScanKey (void) // read buttons \ { unsigned char rekey, rkey, i; I2CStart (); I2CWrByte (0x42); // read command buttons I2Cask (); dio = 1; // read keys before data lines pulled for (i = 0; i <8; i + +) // start reading from the low { Clk = 0; rekey = rekey >> 1; Delay_us(30); clk=1; if(dio) { rekey=rekey|0x80; } else { rekey=rekey|0x00; } Delay_us(30); } I2Cask(); I2CStop(); return (rekey); } void SmgDisplay(void) // Write display register { unsigned char i; I2CStart(); I2CWrByte(0x40); //40H address is automatically incremented by 1 mode, 44H fixed address mode I2Cask(); I2CStop(); I2CStart(); I2CWrByte(0xc0); // Set the first address I2Cask(); for(i=0;i<6;i++) // Addresses from Canada, do not always write address { I2CWrByte(0xff); // Send data I2Cask(); } I2CStop(); I2CStart(); I2CWrByte(0x8f); // Open display, maximum brightness I2Cask(); I2CStop(); } ///========== void init() // Initialization routine { // Initialization slightly } ///========== void main(void) { unsigned char keydate; init(); // Initialization SmgDisplay(); // Write register and open display while(1) { keydate=[b]Scankey[/b](); // Read key value, the key value is not read out for treatment. } } //===========end================ Жирным вsделена функция, написанная с ошибкой (должен быть ScanKey). Я переделал код под STM32: СпойлерКод: #include <stm32f10x.h> #include <main.h> #include <Delay.h> volatile uint16_t Test_1 = 0; unsigned char keydate = 0; /// ==================== void I2CStart (void) // 1637 start { CLK_HIGH; SDA_HIGH; delay_us (2); SDA_LOW; } // ========= void I2Cask (void) // 1637 Answer { CLK_LOW; SDA_INPUT;/////////////////// delay_us (5); // After the falling edge of the eighth clock delay 5us, ACK signals the beginning of judgment while (SDA_STATE); SDA_OUTPUT;/////////////////// CLK_HIGH; delay_us (2); CLK_LOW; } // ==== void I2CStop (void) // 1637 Stop { CLK_LOW; delay_us (2); SDA_LOW; delay_us (2); CLK_HIGH; delay_us (2); SDA_HIGH; } // ===== void I2CWrByte (unsigned char oneByte) // write a byte { unsigned char i; for (i = 0; i <8; i++) { CLK_LOW; if (oneByte & 0x01) // low front {SDA_HIGH;} else {SDA_LOW;} delay_us (3); oneByte = oneByte >> 1; CLK_HIGH; delay_us (3); } } // ---------- - unsigned char ScanKey (void) // read buttons { unsigned char rekey,i; //rkey, was not used I2CStart (); I2CWrByte (0x42); // read command buttons I2Cask (); SDA_HIGH; // read keys before data lines pulled for (i = 0; i <8; i++) // start reading from the low { CLK_LOW; rekey = rekey >> 1; delay_us(30); CLK_HIGH; SDA_INPUT;/////////////////// delay_us(30); /////////////// if(SDA_STATE)///////////////////////////////////////////////////////////////////////Зависает ТУТ!!! { rekey=rekey|0x80; } else { rekey=rekey|0x00; } SDA_OUTPUT;/////////////////// delay_us(30); } I2Cask(); I2CStop(); return (rekey); } void SmgDisplay(void) // Write display register { unsigned char i; I2CStart(); I2CWrByte(0x40); //40H address is automatically incremented by 1 mode, 44H fixed address mode I2Cask(); I2CStop(); I2CStart(); I2CWrByte(0xc0); // Set the first address I2Cask(); for(i=0;i<6;i++) // Addresses from Canada, do not always write address { I2CWrByte(0xff); // Send data I2Cask(); } I2CStop(); I2CStart(); I2CWrByte(0x8f); // Open display, maximum brightness I2Cask(); I2CStop(); } ///========== void init() // Initialization routine { // Initialization slightly } ///========== //===========end================ int main() { //Тактируем ядро RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала RCC->CR &= ~RCC_CR_PLLON; //Отключаем генератор PLL RCC->CR &= ~RCC_CR_HSEON; while((RCC->CR & RCC_CR_HSERDY)!=0) {} RCC->CR |= RCC_CR_HSION; //Включить генератор HSI while((RCC->CR & RCC_CR_HSIRDY)==0) {} RCC->CFGR &= ~RCC_CFGR_SW; //Выбрать источником тактового сигнала HSI while((RCC->CFGR & RCC_CFGR_SWS)!=0) {} // !=0 - HSI; !=4 - HSE; !=8 - PLL; RCC->CFGR &= ~RCC_CFGR_PPRE1; while((RCC->CFGR & RCC_CFGR_PPRE1)!=0){} // !=0 - Not devided; !=1024 - Dev=2; !=1280 - Dev=4; !=1536 - Dev=8; !=1792 - Dev=16; RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; GPIOB->CRL = 0x55444444; __enable_irq (); init();// Initialization SmgDisplay(); // Write register and open display while(1) { keydate = ScanKey(); // Read key value, the key value is not read out for treatment. } } В хедере: СпойлерКод: #define CLK_HIGH (GPIOB->BSRR |= GPIO_BSRR_BS6) #define CLK_LOW (GPIOB->BSRR |= GPIO_BSRR_BR6) #define SDA_HIGH (GPIOB->BSRR |= GPIO_BSRR_BS7) #define SDA_LOW (GPIOB->BSRR |= GPIO_BSRR_BR7) #define CLK_INPUT GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6); GPIOB->CRL |= (GPIO_CRL_CNF6_0) #define CLK_OUTPUT GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6); GPIOB->CRL |= (GPIO_CRL_MODE6_0 | GPIO_CRL_CNF6_0) #define SDA_INPUT GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7); GPIOB->CRL |= (GPIO_CRL_CNF7_0) #define SDA_OUTPUT GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7); GPIOB->CRL |= (GPIO_CRL_MODE7_0 | GPIO_CRL_CNF7_0) #define CLK_STATE (GPIOB->IDR & GPIO_IDR_IDR6) #define SDA_STATE (GPIOB->IDR & GPIO_IDR_IDR7) Вроде все правильно сделал, но код зависает в ожидании второго ACK. Может кто-то делал подобное? Наверное есть какая-то особенность при запуске, про которую я не знаю... ![]() |
Автор: | isx [ Пт май 25, 2018 00:45:53 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
А кто-то вообще писал код для этого чуда?) |
Автор: | Пока_без_кота [ Пт май 25, 2018 07:44:44 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Я писал (переделывал чужую либу под себя). Запись байта осуществляю вот так: СпойлерКод: uint8_t TM1637_write_byte(uint8_t value) { uint8_t i, ack; for (i = 0; i < 8; ++i, value >>= 1) { TM1637_CLK_LOW(); _delay_us(TM1637_DELAY_US); if (value & 0x01) { TM1637_DIO_HIGH(); } else { TM1637_DIO_LOW(); } TM1637_CLK_HIGH(); _delay_us(TM1637_DELAY_US); } TM1637_CLK_LOW(); TM1637_DIO_INPUT(); TM1637_DIO_HIGH(); _delay_us(TM1637_DELAY_US); ack = TM1637_DIO_READ(); if (ack) { TM1637_DIO_OUTPUT(); TM1637_DIO_LOW(); } _delay_us(TM1637_DELAY_US); TM1637_CLK_HIGH(); _delay_us(TM1637_DELAY_US); TM1637_CLK_LOW(); _delay_us(TM1637_DELAY_US); TM1637_DIO_OUTPUT(); return ack; } Оригинал, с короторого передирал, лежит здесь: https://github.com/lpodkalicki/attiny-tm1637-library Когда делали на аппаратном I2C, возможно не учли, что в "каноничном" I2C передача идет старшим байтом вперед, а ТМ1637 принимает младшим байтом вперед. |
Автор: | BOB51 [ Пт май 25, 2018 10:43:44 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Да раскопать бы даташиту путевую под эту микру... ![]() С инглиш проблем нету, а вот с иероглифами я не дружу... ![]() УПС... Поискать поленился http://www.mcielectronics.cl/website_MC ... TM1637.pdf Теперь и пожевать можно... ![]() |
Автор: | musor [ Пт май 25, 2018 10:52:53 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
дык яж на TMxxxxx выкладыввал гето на форум на всю серию шиты искать ленива чето инет тормозит |
Автор: | BOB51 [ Пт май 25, 2018 10:56:42 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Дык... пока на глазы в продаже не попадалась - и не интересовалси, а тут вроде как их расплодилось - а почти все ссыли на китая-маму. Воть накопал - теперь и почитамсс. ![]() |
Автор: | isx [ Пт май 25, 2018 16:28:09 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Только вот отправлять пакеты как в даташитн у меня не получается - не принимает вторую команду и все. |
Автор: | Пока_без_кота [ Пт май 25, 2018 18:43:46 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Копирните либу по моей ссылке 1 в 1. Как заработает - будете разбиратся, что у Вас в коде не так. |
Автор: | BOB51 [ Сб май 26, 2018 05:35:54 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Микросхема одинакова ВСЕГДА, а вот раскладка выводов индикатора относительно выводов микросхемы может отличаться в зависимости от типа светодиодной матрицы и производителя модуля. Посему и картинка может быть отличной. Этот вопрос ранее уже всплывал в темах о ЖКИ индикаторах - вполне возможно и в данном случае может иметь место. Лучше уж самому программы загрузки по даташиту соорудить и протестировать соответствие бит ОЗУ конкретным сегментам индикатора (посегментный тест привязки бит ОЗУ). Тем более, что микросхема обслуживает 6 позиций , а индикаторы типовые на 4-5 позиций (ежли "часовые" точки считать 5-й) какой порядок соответствия установлен в конкретном изделии - надо тестировать. Будет в лапах образец - составлю и прожку (пойдет "текущим хвостом" - продолжением сюда https://radiokot.ru/forum/viewtopic.php ... 7#p3365177 ). ![]() |
Автор: | isx [ Пн май 28, 2018 12:29:59 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Оригинал, с которого передирал, лежит здесь: https://github.com/lpodkalicki/attiny-tm1637-library Завелось таки!!! Основная проблема оказалась задержках. Нужно было увеличить их в 10 РАЗ!!!. Скорее всего это связано с атомарным управлением пинами в STM32. Позже выложу готовый код. Щас надо в порядок его привести. Есть еще вопрос. У меня есть такой код: СпойлерКод: #define CLK_HIGH (GPIOB->BSRR |= GPIO_BSRR_BS0) #define CLK_LOW (GPIOB->BSRR |= GPIO_BSRR_BR0) #define SDA_HIGH (GPIOB->BSRR |= GPIO_BSRR_BS1) #define SDA_LOW (GPIOB->BSRR |= GPIO_BSRR_BR1) #define CLK_INPUT GPIOB->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0); GPIOB->CRL |= (GPIO_CRL_CNF0_0) #define CLK_OUTPUT GPIOB->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0); GPIOB->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_CNF0_0) #define SDA_INPUT GPIOB->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); GPIOB->CRL |= (GPIO_CRL_CNF1_0) #define SDA_OUTPUT GPIOB->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); GPIOB->CRL |= (GPIO_CRL_MODE1_0 | GPIO_CRL_CNF1_0) #define CLK_STATE (GPIOB->IDR & GPIO_IDR_IDR0) #define SDA_STATE (GPIOB->IDR & GPIO_IDR_IDR1) Как можно сделать настройку с помощью функции типа: pinsSet(GPIOB, 0, 1);? Подозреваю, что это должно как-то быть связано с энумерацией, но пока не соображу чет... ![]() |
Автор: | BOB51 [ Ср май 30, 2018 20:37:15 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Эксперименты с "подопытным мышом": https://radiokot.ru/forum/viewtopic.php ... 4#p3389274 ![]() |
Автор: | simq [ Пт дек 04, 2020 12:52:46 ] |
Заголовок сообщения: | Re: Работа с семисегментным дисплеем через TM1637 |
Оригинал, с которого передирал, лежит здесь: https://github.com/lpodkalicki/attiny-tm1637-library Основная проблема оказалась задержках. Нужно было увеличить их в 10 РАЗ!!! Ещё нужно учесть, что если используются резисторы подтяжки только те что на плате, то они там 10кОм и параллельно SDA,SLC ещё по 1000пф ёмкость подпаяна |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |