• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Программирование ATTINY2313A-PU в среде Arduino IDE 1.8.2

nikolz

Well-known member
Светодиоды для наглядности.
Сработает прерывание при наж кнопок, светодиод мигнет.
nikolz - вы ничего не рассказали про ваш метод работы с кнопками.
Или это секрет?
Один из методов раза два уже рассказывал на форуме.
Поэтому рассказывать надцатый раз нет интереса.
===============
можно это написать иначе
PORTB |= (1 << 0) | (1 << 1 ) | (1 << 2);// Set bits - pullup
DDRB &= ~((1 << 0) | (1 << 1) | (1 << 2));// Clear bit - input
PCMSK |= (1 << 0) | (1 << 1) | (1 << 2);// Set bits
---------------------
так:
----------------------
#define mask (1 << 0) | (1 << 1 ) | (1 << 2)
PORTB |= mask;// Set bits - pullup
DDRB &= ~mask;// Clear bit - input
PCMSK |=mask;// Set bits
т е PCMSK равен PORTB верно ?
==============
#define mask (1 << 0) | (1 << 1 ) | (1 << 2)
так:
#define mask 0x7
=================
а сброс маски
DDRB &= ~mask;// Clear bit - input
так:
DDRB^=mask;// Clear bit - input
 

alexlaw

Member
Отслеживаем нажатие 3 кнопок в любом сочетании
Код:
ISR(PCINT_vect) {
  PORTB &= ~((1 << 7)  | (1 <<4)  | (1 <<3));// Clear bit - выкл все светодиоды
  switch(PINB & 0x07){
    case 6:PORTB |= (1 << 3);break;//наж кн pb0 - high pb3
    case 5:PORTB |= (1 << 4);break;//наж кн pb1 - high pb4
    case 4:PORTB |= (1 << 4) | (1 <<3);break;//наж кн pb0 pb1 - high pb4 pb3
    case 3:PORTB |= (1 << 7);break;//наж кн pb2 - high pb7
    case 2:PORTB |= (1 << 7) | (1 <<3);break;//наж кн pb2 pb0 - high pb7 pb3
    case 1:PORTB |= (1 << 7) | (1 <<4);break;//наж кн pb2 pb1 - high pb7 pb4
  }
}
 

alexlaw

Member
Задача подключить бесконечное число кнопок к любому пину или двум которые являются бинарными PIO.
Я конечно не смог, но используя метод
Отслеживаем нажатие 3 кнопок в любом сочетании
и задействовав все 8 портов, можно получить 8!+1=40321 различных состояний порта "B", что практически является бесконечностью.
Вместо кнопок лучше использовать переключатели.
Хотя программно обработать такое кол-во состояний вряд ли возможно.
 

alexlaw

Member
Например с помощью переключателей можно выставить время в RTC.
 

alexlaw

Member
Я конечно перегнул палку.
Всего 255 различных состояний порта "B".
Бывает.
 

nikolz

Well-known member
Я конечно перегнул палку.
Всего 255 различных состояний порта "B".
Бывает.
подсказка
В общем случае подобные задачи я решаю методом измерения времени разряда ( заряда) емкостей.
В частности это могут быть поверхностные , межслойные , слой и палец.
 

alexlaw

Member
Финальный аккорд. Ради чего все затевалось, а именно разгрузить основной МК.
Тинька спит, при этом контролирует кнопки. При нажатии кнопок - просыпается,
отсылает на основной МК какой-то код, соответствующий нажатым кнопкам и
снова засыпает.
Код:
char but;
void setup() {
initButton();
initUSART();
}
void loop() {
  sleepNow();
  USART_Transmit(but);
  delay(500);
}
ISR(PCINT_vect) {
  PORTB &= ~((1 <<4)  | (1 <<3));// Clear bit - выкл все светодиоды
  switch(PINB & 0x03){   
    case 2:{PORTB |= (1 <<3);
    but=0x41;//A
    break;}// - high  pb3
    case 1:{PORTB |= (1 <<4);
    but=0x42;//B
    break;}// - high  pb4
    case 0:{PORTB |=(1 <<4) | (1 <<3);
    but=0x43;//C
    break;}// - high pb4 pb3
  }
}
void sleepNow() {
/*
* Idle  (режим холостого хода)
* В этом режиме прекращается формирование тактовых сигналов clk CPU и  clk FLASH .
* При  этом  ЦПУ  микроконтроллера  останавливается,  а  все остальные  периферийные  устройства
* (интерфейсные  модули,  таймеры/счетчики,  аналоговый  компаратор,  АЦП,  сторожевой  таймер),
* а также  подсистема  прерываний  продолжают  функционировать.
*/
/*Если компаратор не используется, то при переводе микроконтроллера в
* режим Idle или ADC Noise Reduction его необходимо отключить. В других
* «спящих» режимах модуль аналогового компаратора отключается автома
* тически. */ 
DIDR |= (1 << AIN1D)  | (1 << AIN0D ); // Set bits - отключения  входных  цифровых буферов
ACSR |= (1 << ACD);// Set bits - Выключение компаратора
/*
*Аналогоцифровой преобразователь
* Если функционирование АЦП разрешено, то он будет работать во всех
* «спящих»  режимах.  Соответственно,  для  снижения  потребляемого  тока
* модуль АЦП необходимо отключать перед переводом микроконтроллера в
* любой из энергосберегающих режимов.
*/
//Режим энергосбережения
MCUCR |= (1 << SM0);// Set bits - Power Down
MCUCR |= (1 << SE);// Set bits -  sleep_enable
asm ("sleep");
MCUCR &= ~(1 << SE);// Clear bit - sleep_disable
}
void initButton() {
//pb0 pb1  кнопки
//pb3 pb4 светодиод  
PORTB |= (1 << 0) | (1 << 1 );// Set bits - pullup
DDRB &= ~((1 << 0)  | (1 << 1));// Clear bit - input 
PORTB &= ~((1 << 3)  |  (1 << 4));// Clear bit - low
DDRB |= (1 << 3) | (1 << 4);// Set bits - output
GIMSK |= (1 << PCIE);// Set bits - Разрешение прерывания по изменению состояния выводов 0й группы - PCINT.
//PCMSK Определяют условие генерации прерывания PCI0. Если какойлибо
//бит установлен в 1, то изменение состояния соответствующего вывода
//вызовет генерацию прерывания
PCMSK |= (1 << 0) | (1 << 1);// Set bits -прерывание по изменению состояния вывода 0 или 1 - PCINT 
}
void initUSART() {
//UCSRB &= ~((1 << TXEN) | (1 << RXEN)); // Clear bit 
//запретить прнерывания от передатчика
UCSRB &= ~((1 << RXCIE) | (1 << TXCIE) | (1 << UDRIE)); // Clear bit
//Если бит UMSEL сброшен в 0, то модуль работает в асинхронном режиме
//USBS Количество стопбитов. Если бит сброшен в 0, то передатчик посылает 1 стопбит,
//если установлен в 1, то 2 стопбита.
//UCPOL  При работе в асинхронном режиме он должен быть сброшен в 0. USART Mode: Asynchronous
//UPM1 UPM0 - Управление схемой контроля четности - 0 0 Выключена
UCSRC &= ~((1 << UMSEL) | (1 << USBS) | (1 << UCPOL) | (1 << UPM1) | (1 << UPM0)); // Clear bit
//Определение размера слова данных - 8 бит
UCSRC |= (1<<UCSZ1) | (1<<UCSZ0); // Set bits
UCSRA &= ~(1 << UCSZ2); // Clear bit
//UCSRC &= ~(1 << U2X); // Clear bit  обычная скорость
// Speed = 9600
UBRRH = 0;
UBRRL = 51;
//Разрешение передачи
UCSRB |=(1<<TXEN); // Set bits
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */ 
   while ( !( UCSRA & (1<<UDRE))) {   
   };
   UDR = data;    
}
com_3.png
Светодиоды нужны только для наглядности.
IMG_20190715_074705.jpg
 

nikolz

Well-known member
Финальный аккорд. Ради чего все затевалось, а именно разгрузить основной МК.
Тинька спит, при этом контролирует кнопки. При нажатии кнопок - просыпается,
отсылает на основной МК какой-то код, соответствующий нажатым кнопкам и
снова засыпает.
Код:
char but;
void setup() {
initButton();
initUSART();
}
void loop() {
  sleepNow();
  USART_Transmit(but);
  delay(500);
}
ISR(PCINT_vect) {
  PORTB &= ~((1 <<4)  | (1 <<3));// Clear bit - выкл все светодиоды
  switch(PINB & 0x03){  
    case 2:{PORTB |= (1 <<3);
    but=0x41;//A
    break;}// - high  pb3
    case 1:{PORTB |= (1 <<4);
    but=0x42;//B
    break;}// - high  pb4
    case 0:{PORTB |=(1 <<4) | (1 <<3);
    but=0x43;//C
    break;}// - high pb4 pb3
  }
}
void sleepNow() {
/*
* Idle  (режим холостого хода)
* В этом режиме прекращается формирование тактовых сигналов clk CPU и  clk FLASH .
* При  этом  ЦПУ  микроконтроллера  останавливается,  а  все остальные  периферийные  устройства
* (интерфейсные  модули,  таймеры/счетчики,  аналоговый  компаратор,  АЦП,  сторожевой  таймер),
* а также  подсистема  прерываний  продолжают  функционировать.
*/
/*Если компаратор не используется, то при переводе микроконтроллера в
* режим Idle или ADC Noise Reduction его необходимо отключить. В других
* «спящих» режимах модуль аналогового компаратора отключается автома
* тически. */
DIDR |= (1 << AIN1D)  | (1 << AIN0D ); // Set bits - отключения  входных  цифровых буферов
ACSR |= (1 << ACD);// Set bits - Выключение компаратора
/*
*Аналогоцифровой преобразователь
* Если функционирование АЦП разрешено, то он будет работать во всех
* «спящих»  режимах.  Соответственно,  для  снижения  потребляемого  тока
* модуль АЦП необходимо отключать перед переводом микроконтроллера в
* любой из энергосберегающих режимов.
*/
//Режим энергосбережения
MCUCR |= (1 << SM0);// Set bits - Power Down
MCUCR |= (1 << SE);// Set bits -  sleep_enable
asm ("sleep");
MCUCR &= ~(1 << SE);// Clear bit - sleep_disable
}
void initButton() {
//pb0 pb1  кнопки
//pb3 pb4 светодиод 
PORTB |= (1 << 0) | (1 << 1 );// Set bits - pullup
DDRB &= ~((1 << 0)  | (1 << 1));// Clear bit - input
PORTB &= ~((1 << 3)  |  (1 << 4));// Clear bit - low
DDRB |= (1 << 3) | (1 << 4);// Set bits - output
GIMSK |= (1 << PCIE);// Set bits - Разрешение прерывания по изменению состояния выводов 0й группы - PCINT.
//PCMSK Определяют условие генерации прерывания PCI0. Если какойлибо
//бит установлен в 1, то изменение состояния соответствующего вывода
//вызовет генерацию прерывания
PCMSK |= (1 << 0) | (1 << 1);// Set bits -прерывание по изменению состояния вывода 0 или 1 - PCINT
}
void initUSART() {
//UCSRB &= ~((1 << TXEN) | (1 << RXEN)); // Clear bit
//запретить прнерывания от передатчика
UCSRB &= ~((1 << RXCIE) | (1 << TXCIE) | (1 << UDRIE)); // Clear bit
//Если бит UMSEL сброшен в 0, то модуль работает в асинхронном режиме
//USBS Количество стопбитов. Если бит сброшен в 0, то передатчик посылает 1 стопбит,
//если установлен в 1, то 2 стопбита.
//UCPOL  При работе в асинхронном режиме он должен быть сброшен в 0. USART Mode: Asynchronous
//UPM1 UPM0 - Управление схемой контроля четности - 0 0 Выключена
UCSRC &= ~((1 << UMSEL) | (1 << USBS) | (1 << UCPOL) | (1 << UPM1) | (1 << UPM0)); // Clear bit
//Определение размера слова данных - 8 бит
UCSRC |= (1<<UCSZ1) | (1<<UCSZ0); // Set bits
UCSRA &= ~(1 << UCSZ2); // Clear bit
//UCSRC &= ~(1 << U2X); // Clear bit  обычная скорость
// Speed = 9600
UBRRH = 0;
UBRRL = 51;
//Разрешение передачи
UCSRB |=(1<<TXEN); // Set bits
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */
   while ( !( UCSRA & (1<<UDRE))) {  
   };
   UDR = data;   
}
Посмотреть вложение 7635
Светодиоды нужны только для наглядности.
Посмотреть вложение 7636
Если это и есть цель, то вот простейшее решение
кнопки подключаются на RST или CH_ED
ESP спит либо вооще в дауне
нажимаем кнопки и ESP просыпается и делает по нужде и снова спит
и не надо ничего довешивать кроме кнопок на один пин
 

alexlaw

Member
Код:
//-----------------------------------------------------------------------------
/*                                   ATTINY2313
                             =========================
                          ATTINY      ARDUINO     ATTINY
                   PA0/XTAL1 || 5 -  3        9 - 12 || PB0/AIN0/PCINT0    
                   PA1/XTAL2 || 4 -  2       10 - 13 || PB1/AIN1/PCINT1
                   PA2/RESET || 1 -  17      11 - 14 || PB2/OC0A/PCINT2
                             ||              12 - 15 || PB3/OC1A/PCINT3   
                     PD0/RXD || 2 -  0       13 - 16 || PB4/OC1B/PCINT4
                     PD1/TXD || 3 -  1       14 - 17 || PB5/MOSI/DI/SDA/PCINT5
          PD2/INT0/XCK/CKOUT || 6 -  4       15 - 18 || PB6/MISO/DO/PCINT6
                    PD3/INT1 || 7 -  5       16 - 19 || PB7/USCK/SCL/PCINT7
                      PD4/T0 || 8 -  6               ||
                 PD5/T1/OC0B || 9 -  7               ||
                     PD6/ICP || 11 - 8               ||
                          ATTINY      ARDUINO     ATTINY                  
                             =========================
                                     ATTINY2313    */
//-----------------------------------------------------------------------------                                    
const int clock1 = 3;
const int data1 = 2;
                 /*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
uint8_t digits1[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};
//uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D };
int slaveSelect=14;//PB5
int din=16;//PB7
int clk=15;//PB6
uint8_t TimeBytes[] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};
boolean b = false;
byte dot = 128;//двоеточие на дисплее индикатора
void setup() { 
PORTB |= (1 << 4);// Set bits - pullup
DDRB &= ~(1 << 4);// Clear bit - input 
PORTB &= ~(1 << 3);// Clear bit - low
DDRB |= (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) ;// Set bits - output
GIMSK |= (1 << PCIE);// Set bits - Разрешение прерывания по изменению состояния выводов 0й группы - PCINT.
//PCMSK Определяют условие генерации прерывания PCI0. Если какойлибо
//бит установлен в 1, то изменение состояния соответствующего вывода
//вызовет генерацию прерывания
PCMSK |= (1 << 4);// Set bits -прерывание по изменению состояния вывода 4
pinMode(clock1, OUTPUT);
pinMode(data1, OUTPUT);
start(clock1,data1);
writeValue(clock1,data1,0x8c);
stop(clock1,data1);
// clear display
write(clock1,data1,0x00, 0x00, 0x00, 0x00);
watch_dog_ext();
}
void loop() {
if (b) SetTime(); 
data1302();
uint8_t h = TimeBytes[2];
uint8_t m = TimeBytes[1];
if (TimeBytes[0]&0x01) dot=0; else dot=128;
write(clock1,data1,digits1[(h & 0xF0) >> 4],digits1 [h & 0x0F] | dot,digits1[(m & 0xF0) >> 4],digits1 [m & 0x0F]);
//delay(1000);
sleepNow();
}
void sendCommand1302(byte cmd, byte data)
{
digitalWrite(slaveSelect,HIGH); //chip select is active HIGH
// передать старший байт
shiftOut(din, clk, LSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, LSBFIRST, data);
digitalWrite(slaveSelect,LOW);
}
void data1302()
{
//Команда clock burst read с кодом 0xBF считывает текущее состояние часов
//В ответ RTC посылают 7 байт, в которых хранятся соответственно
//секунды, минуты, часы, день, месяц, день недели, год, и кое-какие флаги 
digitalWrite(slaveSelect,HIGH); //chip select is active HIGH
// передать  байт
shiftOut(din, clk, LSBFIRST, 0xBF);
pinMode(din, INPUT);
for(int i = 0; i < 7; i++){
TimeBytes[i]=readByte();
}
digitalWrite(slaveSelect,LOW);
pinMode(din, OUTPUT);
}
uint8_t readByte()
{
  uint8_t value = 0;
  uint8_t currentBit = 0;

  for (int i = 0; i < 8; ++i)
  {
    currentBit = digitalRead(din);
    value |= (currentBit << i);
    digitalWrite(clk, HIGH);
    delayMicroseconds(1);
    digitalWrite(clk, LOW);
  }
  return value;
}
void SetTime()
{
//УСТАНОВИТЬ ВРЕМЯ
  sendCommand1302(0x86, 0x24);//день
  sendCommand1302(0x88, 0x07);//месяц
  sendCommand1302(0x8C, 0x19);//год
  sendCommand1302(0x84, 0x21);//час
  sendCommand1302(0x82, 0x00);//мин
  sendCommand1302(0x80, 0x00);//сек
  sendCommand1302(0x8A, 0x03);//день недели
  b = false;
}
ISR(PCINT_vect) {
  if (PINB>>4 & 0x01) PORTB &= ~(1 << 3);// Clear bit - low
  else PORTB |= (1 << 3);// Set bits - high
  b = true;
}
void write(int clock,int data,uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
{
start(clock,data);
writeValue(clock,data,0x40);
stop(clock,data);
start(clock,data);
writeValue(clock,data,0xc0);
writeValue(clock,data,first);
writeValue(clock,data,second);
writeValue(clock,data,third);
writeValue(clock,data,fourth);
stop(clock,data);
}

void start(int clock,int data)
{
digitalWrite(clock,HIGH);//send start signal to TM1637
digitalWrite(data,HIGH);
delayMicroseconds(5);
digitalWrite(data,LOW);
digitalWrite(clock,LOW);
delayMicroseconds(5);
}
void stop(int clock,int data)
{
digitalWrite(clock,LOW);
digitalWrite(data,LOW);
delayMicroseconds(5);
digitalWrite(clock,HIGH);
digitalWrite(data,HIGH);
delayMicroseconds(5);
}
bool writeValue(int clock,int data,uint8_t value)
{
for(uint8_t i = 0; i < 8; i++)
{
digitalWrite(clock, LOW);
delayMicroseconds(5);
digitalWrite(data, (value & (1 << i)) >> i);
delayMicroseconds(5);
digitalWrite(clock, HIGH);
delayMicroseconds(5);
}
// wait for ACK
digitalWrite(clock,LOW);
delayMicroseconds(5);
pinMode(data,INPUT);
digitalWrite(clock,HIGH);
delayMicroseconds(5);
bool ack = digitalRead(data) == 0;
pinMode(data,OUTPUT);
return ack;
}
void sleepNow() {
/*
* Idle  (режим холостого хода)
* В этом режиме прекращается формирование тактовых сигналов clk CPU и  clk FLASH .
* При  этом  ЦПУ  микроконтроллера  останавливается,  а  все остальные  периферийные  устройства
* (интерфейсные  модули,  таймеры/счетчики,  аналоговый  компаратор,  АЦП,  сторожевой  таймер),
* а также  подсистема  прерываний  продолжают  функционировать.
*/
/*Если компаратор не используется, то при переводе микроконтроллера в
* режим Idle или ADC Noise Reduction его необходимо отключить. В других
* «спящих» режимах модуль аналогового компаратора отключается автома
* тически. */ 
DIDR |= (1 << AIN1D)  | (1 << AIN0D ); // Set bits - отключения  входных  цифровых буферов
ACSR |= (1 << ACD);// Set bits - Выключение компаратора
/*
*Аналогоцифровой преобразователь
* Если функционирование АЦП разрешено, то он будет работать во всех
* «спящих»  режимах.  Соответственно,  для  снижения  потребляемого  тока
* модуль АЦП необходимо отключать перед переводом микроконтроллера в
* любой из энергосберегающих режимов.
*/
//Режим энергосбережения
//MCUCR &= ~((1 << SM1) | (1 << SM0));// Clear bit  - Idle -не у меня не работает?
MCUCR |= (1 << SM0);// Set bits - Power Down
MCUCR |= (1 << SE);// Set bits -  sleep_enable
asm ("sleep");
MCUCR &= ~(1 << SE);// Clear bit - sleep_disable
}
void watch_dog_ext(){
//расширенный  сторожевой  таймер
/*
* для выключения таймера (сброса бита WDE) необходимо выполнить следующие действия:
* 1. Одной командой записать 1 в биты WDE и WDCE.
* 2. В течение следующих четырех тактов записать 0 в бит WDE.
*/
/*
* Обратите внимание на то, что состояние флага сброса WDRF регистра MCUSR отменяет состояние бита WDE. Это означает, что бит WDE уста
* новлен всегда, когда установлен флаг WDRF, поэтому перед сбросом WDE необходимо также сбросить WDRF.
*/
//MCUSR &= ~(1 << WDRF);// Clear bit
//WDTCSR |= (1 << WDE)  | (1 << WDCE); // Set bits
//WDTCSR &= ~(1 << WDE);// Clear bit
/*
* Для изменения периода таймаута необходимо выполнить следующие действия:
* 1. Одной командой записать 1 в биты WDE и WDCE.
* 2. В течение следующих четырех тактов записать требуемое значение в биты WDP3:0 и WDE, одновременно сбрасывая бит WDCE.
* Перед  изменением  битов  WDP3:0  сторожевой  таймер  рекомендуется сбрасывать.
* Сброс сторожевого таймера осуществляется командой WDR.
*/
asm ("WDR");
WDTCSR |= (1 << WDE)  | (1 << WDCE); // Set bits
//1 сек
WDTCSR |= (1 << WDP1  | (1 << WDP2)); // Set bits
WDTCSR &= ~((1 << WDP0)  | (1 << WDP3));// Clear bit
WDTCSR &= ~(1 << WDCE);// Clear bit

MCUSR &= ~(1 << WDRF);// Clear bit
WDTCSR |= (1 << WDE)  | (1 << WDCE); // Set bits
WDTCSR &= ~(1 << WDE);// Clear bit

WDTCSR |= (1 << WDIE);// Set bits - Разрешение прерывания от сторожевого таймера (сбрасывается после сраб тайм аута)
}
ISR(WDT_OVERFLOW_vect) { //1 сек
dot = 128;
}
На досуге собрал часы (на дальнем плане).
Работают на CR2032.
IMG_20190722_141009.jpg
Может кому пригодится.
ds1302_tm1637.png
 

nikolz

Well-known member
мощные.
Но индикатор почему-то меньше платы.
Наверное поверхностный монтаж ?
На руси так всегда
вроде нормальная идея - а воплощение - ужас какой-то.
 

alexlaw

Member
Недавно перечитал эту ветку и увидел, что забыл важную деталь.
Попробовать i2c.
Попробовал на на часах ds3231.
Код:
/*                 DS3231
/                 ___________  
/        32kHz   | 1      16 | SCL
/         Vcc    | 2      15 | SDA
/       INT/SOW  | 3      14 | Vbat
/         RST    | 4      13 | GND
/                | 5      12 |
/                | 6      11 |
/                | 7      10 |
/                | 8      9  |
/                |___________|
/ SCL,SDA,INT/SOW,32kHz подтянуть к + через резистор 4,7к
//-----------------------------------------------------------------------------
                                    ATTINY2313
                             =========================
                          ATTINY      ARDUINO     ATTINY
                   PA0/XTAL1 || 5 -  3        9 - 12 || PB0/AIN0/PCINT0   
                   PA1/XTAL2 || 4 -  2       10 - 13 || PB1/AIN1/PCINT1
                   PA2/RESET || 1 -  17      11 - 14 || PB2/OC0A/PCINT2
                             ||              12 - 15 || PB3/OC1A/PCINT3  
                     PD0/RXD || 2 -  0       13 - 16 || PB4/OC1B/PCINT4
                     PD1/TXD || 3 -  1       14 - 17 || PB5/MOSI/DI/ SDA /PCINT5
          PD2/INT0/XCK/CKOUT || 6 -  4       15 - 18 || PB6/MISO/DO/PCINT6
                    PD3/INT1 || 7 -  5       16 - 19 || PB7/USCK/ SCL /PCINT7
                      PD4/T0 || 8 -  6               ||
                 PD5/T1/OC0B || 9 -  7               ||
                     PD6/ICP || 11 - 8               ||
                          ATTINY      ARDUINO     ATTINY                 
                             =========================
                                     ATTINY2313  
//-----------------------------------------------------------------------------
*/

//http://www.technoblogy.com/show?24R7
//https://github.com/technoblogy/tiny-i2c
#include <TinyI2CMaster.h>
const int RTCaddress = 0x68;
const int clock1 = 6;
const int data1 = 7;
                 /*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
//uint8_t digits1[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};
uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D, 0x7E, 0x67, 0x0F, 0x73, 0x4F, 0x4E};
//byte second, minute, hour, date, month, year;
uint8_t TimeBytes[] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};
byte dot = 128;//двоеточие на дисплее индикатора
uint8_t temp;
boolean viewTemperature;
uint8_t _reg_status;
void setup() {
TinyI2C.init();
pinMode(clock1, OUTPUT);
pinMode(data1, OUTPUT);
start(clock1,data1);
writeValue(clock1,data1,0x8c);
stop(clock1,data1);
// clear display
write(clock1,data1,0x00, 0x00, 0x00, 0x00);
//SetTime_ds3231();
resetAlarm();
}

void loop() {
GetTime_ds3231();
uint8_t h = TimeBytes[2];
uint8_t m = TimeBytes[1];
if (TimeBytes[0]&0x01) dot=0; else dot=128;
// write(clock1,data1,digits1[(h & 0xF0) >> 4],digits1 [h & 0x0F] | dot,digits1[(m & 0xF0) >> 4],digits1 [m & 0x0F]);
if (viewTemperature){
write(clock1,data1,0x0F,0x5C,digits1 [temp % 10],digits1[(temp / 10)]);
} else {
write(clock1,data1,digits1 [m & 0x0F],digits1[(m & 0xF0) >> 4] | dot,digits1 [h & 0x0F],digits1[(h & 0xF0) >> 4]);
}
delay(1000);
}

void GetTime_ds3231() {
    TinyI2C.start(RTCaddress, 0);                // Start I2C protocol with DS3231 address
    TinyI2C.write(0);                            // Send register address
    TinyI2C.restart(RTCaddress, 7);               // Request 7 bytes from DS3231 and release I2C bus at end of reading
//    second = TinyI2C.read();                         // Read seconds from register 0
//    minute = TinyI2C.read();                         // Read minuts from register 1
//    hour   = TinyI2C.read();                         // Read hour from register 2
//    TinyI2C.read();                                  // Read day from register 3 (not used)
//    date   = TinyI2C.read();                         // Read date from register 4
//    month  = TinyI2C.read();                         // Read month from register 5
//    year   = TinyI2C.read();                         // Read year from register 6
    for(int i = 0; i < 7; i++){
      TimeBytes[i]=TinyI2C.read();
    }
    TinyI2C.stop();
      if ((int)(TimeBytes[0] & 0x0F) % 10 == 0){//каждые 10 сек показ температуру
         viewTemperature=true;
        getTemperture();
      } else viewTemperature=false;
}
void SetTime_ds3231() {
        // Write data to DS3231 RTC
      TinyI2C.start(RTCaddress, 0);                  // Start I2C protocol with DS3231 address
      TinyI2C.write(0);                              // Send register address    
      TinyI2C.write(0);                              // Reset sesonds and start oscillator
      TinyI2C.write(0x48);                           // Write minute
      TinyI2C.write(0x21);                           // Write hour
      TinyI2C.write(0x06);                           // Write day (not used)
      TinyI2C.write(0x31);                           // Write date
      TinyI2C.write(0x08);                           // Write month
      TinyI2C.write(0x19);                           // Write year
      TinyI2C.stop();                                // Stop transmission and release the I2C bus
}
void getTemperture()
{
  TinyI2C.start(RTCaddress, 0);                 // Start I2C protocol with DS3231 address
  TinyI2C.write(0x11);                        // Send register address
  TinyI2C.restart(RTCaddress, 2);                    // Request 2 bytes from DS3231 and release I2C bus at end of reading
  uint8_t _msb = TinyI2C.read();
  uint8_t _lsb = TinyI2C.read();
//  float temp = (float)_msb + ((_lsb >> 6) * 0.25f);
  TinyI2C.stop(); 
            temp = _msb;
}
//Поскольку при первом включении питания бит INTCN устанавливается в логическую единицу,
//на выводе по умолчанию выводится прерывание с отключенными тревогами.
void resetAlarm()//
{
readStatus();
//сброс флагов Alarm1 и Alarm2
_reg_status &= ~((1 << 0) | (1 << 1));// Clear bit 0(Alarm1), bit 1(Alarm2)
      TinyI2C.start(RTCaddress, 0);                  // Start I2C protocol with DS3231 address
      TinyI2C.write(0x0F);                           // Send register address  Status Register (0Fh)        
      TinyI2C.write(_reg_status);                    // сброс флагов Alarm1 и Alarm2
      TinyI2C.stop();
//Alarm1    
      TinyI2C.start(RTCaddress, 0);                  // Start I2C protocol with DS3231 address
      TinyI2C.write(0x07);                           // Send register address  Alarm 1          
      TinyI2C.write(0x00);                           // Alarm 1
      TinyI2C.write(0x00);                         
      TinyI2C.write(0x00);
      TinyI2C.write(0x00);
      TinyI2C.stop();                               // Stop transmission and release the I2C bus  
//Alarm1
//Alarm2    
      TinyI2C.start(RTCaddress, 0);                  // Start I2C protocol with DS3231 address
      TinyI2C.write(0x0B);                           // Send register address  Alarm 2          
      TinyI2C.write(0x00);                         
      TinyI2C.write(0x00);                  
      TinyI2C.write(0x00);
      TinyI2C.stop();                     // Stop transmission and release the I2C bus   
//Alarm2
      TinyI2C.start(RTCaddress, 0);                   // Start I2C protocol with DS3231 address
      TinyI2C.write(0x0E);                           // Send register address - Control Register (0Eh)
//Bit 2: Interrupt Control (INTCN). This bit controls the
//INT/SQW signal. When the INTCN bit is set to logic 0, a
//square wave is output on the INT/SQW pin         
      TinyI2C.write(0x04);                           // Alarm  Interrupt desable
      TinyI2C.stop();                               // Stop transmission and release the I2C bus
      
}
void readStatus(){
  TinyI2C.start(RTCaddress, 0);                    // Start I2C protocol with DS3231 address
  TinyI2C.write(0x0F);                             // Send register address REG_STATUS
  TinyI2C.restart(RTCaddress, 1);                  // Request 1 bytes from DS3231 and release I2C bus at end of reading                
  _reg_status = TinyI2C.read();
  TinyI2C.stop();  
}
void write(int clock,int data,uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
{
start(clock,data);
writeValue(clock,data,0x40);
stop(clock,data);
start(clock,data);
writeValue(clock,data,0xc0);
writeValue(clock,data,first);
writeValue(clock,data,second);
writeValue(clock,data,third);
writeValue(clock,data,fourth);
stop(clock,data);
}

void start(int clock,int data)
{
digitalWrite(clock,HIGH);//send start signal to TM1637
digitalWrite(data,HIGH);
delayMicroseconds(5);
digitalWrite(data,LOW);
digitalWrite(clock,LOW);
delayMicroseconds(5);
}


void stop(int clock,int data)
{
digitalWrite(clock,LOW);
digitalWrite(data,LOW);
delayMicroseconds(5);
digitalWrite(clock,HIGH);
digitalWrite(data,HIGH);
delayMicroseconds(5);
}

bool writeValue(int clock,int data,uint8_t value)
{
for(uint8_t i = 0; i < 8; i++)
{
digitalWrite(clock, LOW);
delayMicroseconds(5);
digitalWrite(data, (value & (1 << i)) >> i);
delayMicroseconds(5);
digitalWrite(clock, HIGH);
delayMicroseconds(5);
}
// wait for ACK
digitalWrite(clock,LOW);
delayMicroseconds(5);
pinMode(data,INPUT);
digitalWrite(clock,HIGH);
delayMicroseconds(5);
bool ack = digitalRead(data) == 0;
pinMode(data,OUTPUT);
return ack;
}
 

alexlaw

Member
Удалось подключить дисплей lcd1602 по I2C к Attiny2313.
Правда библиотеку LiquidCrystal_I2C до конца не допилил,
чтобы одновременно работала и для Attiny и для Ардуино.
С Attiny2313 - работает.
 

Вложения

alexlaw

Member
Удалось подключить дисплей lcd1602 по I2C к Attiny2313.
Правда библиотеку LiquidCrystal_I2C до конца не допилил,
чтобы одновременно работала и для Attiny и для Ардуино.
С Attiny2313 - работает.
 

Вложения

alexlaw

Member
Удалось подключить дисплей lcd1602 по I2C к Attiny2313.
Правда библиотеку LiquidCrystal_I2C до конца не допилил,
чтобы одновременно работала и для Attiny и для Ардуино.
С Attiny2313 - работает.
 

alexlaw

Member
Пожалуйста удалите лишние посты.
Случайно продублировались.
 

alexlaw

Member
Решил сделать выносной терминал на Attiny2313.
Technoblogy - Tiny Terminal - оригинальный проект на ATtiny85.
1-й этап - подключение дисплея ssd1306.
Код:
int const clk = 0;//9; //D0,SCL,CLK,SCK - Clock - PB0
int const data = 1;//10;//D1,SDA,MOSI - Data - PB1
int const res = 2;//11,RES - Reset - PB2//можно сразу к +
int const dc = 3;//12;DC - Data/Command - PB3
int const cs = 4;//13;CS - Chip Select - PB4

// Initialisation sequence for OLED module
int const InitLen = 23;
unsigned char Init[InitLen] = {
  0xAE, // Display off
  0xD5, // Set display clock
  0x80, // Recommended value
  0xA8, // Set multiplex
  0x3F,
  0xD3, // Set display offset
  0x00,
  0x40, // Zero start line
  0x8D, // Charge pump
  0x14,
  0x20, // Memory mode
  0x02, // Page addressing
  0xA1, // 0xA0/0xA1 flip horizontally
  0xC8, // 0xC0/0xC8 flip vertically
  0xDA, // Set comp ins
  0x12,
  0x81, // Set contrast
  0x7F,
  0xD9, // Set pre charge
  0xF1,
  0xDB, // Set vcom detect
  0x40,
  0xA6  // Normal (0xA7=Inverse)
};
// Character set - stored in program memory
const uint8_t CharMap[96][6] PROGMEM = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00 },
{ 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 },
{ 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00 },
{ 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00 },
{ 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 },
{ 0x36, 0x49, 0x56, 0x20, 0x50, 0x00 },
{ 0x00, 0x08, 0x07, 0x03, 0x00, 0x00 },
{ 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00 },
{ 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00 },
{ 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00 },
{ 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 },
{ 0x00, 0x80, 0x70, 0x30, 0x00, 0x00 },
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 },
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },
{ 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 },
{ 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00 },
{ 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00 },
{ 0x72, 0x49, 0x49, 0x49, 0x46, 0x00 },
{ 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00 },
{ 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00 },
{ 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 },
{ 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00 },
{ 0x41, 0x21, 0x11, 0x09, 0x07, 0x00 },
{ 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 },
{ 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00 },
{ 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 },
{ 0x00, 0x40, 0x34, 0x00, 0x00, 0x00 },
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 },
{ 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 },
{ 0x02, 0x01, 0x59, 0x09, 0x06, 0x00 },
{ 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00 },
{ 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00 },
{ 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00 },
{ 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00 },
{ 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00 },
{ 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00 },
{ 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00 },
{ 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00 },
{ 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00 },
{ 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00 },
{ 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00 },
{ 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00 },
{ 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00 },
{ 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00 },
{ 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00 },
{ 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00 },
{ 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00 },
{ 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00 },
{ 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00 },
{ 0x26, 0x49, 0x49, 0x49, 0x32, 0x00 },
{ 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00 },
{ 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00 },
{ 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00 },
{ 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00 },
{ 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 },
{ 0x03, 0x04, 0x78, 0x04, 0x03, 0x00 },
{ 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00 },
{ 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00 },
{ 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 },
{ 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00 },
{ 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 },
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 },
{ 0x00, 0x03, 0x07, 0x08, 0x00, 0x00 },
{ 0x20, 0x54, 0x54, 0x78, 0x40, 0x00 },
{ 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00 },
{ 0x38, 0x44, 0x44, 0x44, 0x28, 0x00 },
{ 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00 },
{ 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 },
{ 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00 },
{ 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00 },
{ 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00 },
{ 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00 },
{ 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00 },
{ 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00 },
{ 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00 },
{ 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00 },
{ 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00 },
{ 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 },
{ 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00 },
{ 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00 },
{ 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00 },
{ 0x48, 0x54, 0x54, 0x54, 0x24, 0x00 },
{ 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00 },
{ 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00 },
{ 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00 },
{ 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00 },
{ 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 },
{ 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00 },
{ 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00 },
{ 0x00, 0x08, 0x36, 0x41, 0x00, 0x00 },
{ 0x00, 0x00, 0x77, 0x00, 0x00, 0x00 },
{ 0x00, 0x41, 0x36, 0x08, 0x00, 0x00 },
{ 0x02, 0x01, 0x02, 0x04, 0x02, 0x00 },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }
};
int Line, Column, Scroll;
int thisByte = 33;
void setup() {
//clk = 0;//9; //D0,SCL,CLK,SCK - Clock - PB0
//data = 1;//10;//D1,SDA,MOSI - Data - PB1
//res = 2;//11 - PB2
//dc = 3;//12; //-Data/Command - PB3
//cs = 4;//13;//-Chip Select - PB4
  // Define pins
//  pinMode(11, OUTPUT); digitalWrite(11,HIGH);//res
//  pinMode(12, OUTPUT); digitalWrite(12,HIGH);//dc
//  pinMode(9, OUTPUT); digitalWrite(9,HIGH);//clk
//  pinMode(10, OUTPUT);//data
//  pinMode(13, OUTPUT); digitalWrite(13,HIGH);//cs
  PORTB |= (1 << res);/// Set bits - high
  DDRB |= (1 << res);// Set bits - output
  PORTB &= ~(1 << data);// Clear bit - low
  PORTB |= (1 << cs) | (1 << dc) | (1 << clk);/// Set bits - high
  DDRB |= (1 << data) | (1 << cs) | (1 << dc) | (1 << clk);// Set bits - output

  InitDisplay();
  ClearDisplay();
  Command(0xAF);  // Display on
//  Print('q');Print('w');Print('e');Print('r');Print('t');Print('y');
}

void loop() {
  //"ASCII Table"
  if (thisByte < 126){
    Print(thisByte);Print(' ');
    thisByte++;
  } 
  delay(1000); 
}

// Write a data byte to the display
void Data(uint8_t d) { 
  PINB = 1<<cs; // cs low
  for (uint8_t bit = 0x80; bit; bit >>= 1) {
    PINB = 1<<clk; // clk low
    if (d & bit) PORTB = PORTB | (1<<data); else PORTB = PORTB & ~(1<<data);
    PINB = 1<<clk; // clk high
  }
  PINB = 1<<cs; // cs high
}

// Write a command byte to the display
void Command(uint8_t c) {
  PINB = 1<<dc; // dc low
 
  Data(c);
  PINB = 1<<dc; // dc high
}

void InitDisplay () {
  for (uint8_t c=0; c<InitLen; c++) Command(Init[c]);
 
}
// Character terminal **********************************************
void Clear256() {
  uint8_t b = 0;
  do {
    PINB = 1<<clk; // clk low
    b++;
    PINB = 1<<clk; // clk high
  } while (b != 0);
}

// Optimised for fast scrolling
void ClearLine (int line) {
  Command(0xB0 + line);
  Command(0x00); // Column start low
  Command(0x00); // Column start high
  PINB = 1<<cs; // cs low
  PORTB = PORTB & ~(1<<data); // data low
  Clear256(); Clear256(); Clear256(); Clear256();
  PINB = 1<<cs; // cs high
}

void ClearDisplay () {
  for (uint8_t p=0; p < 8; p++) ClearLine(p);
  Line = Scroll;
  Column = 0;
}

// Clears the top line, then scrolls the display up by one line
void ScrollDisplay () {
  ClearLine(Scroll);
  Scroll = (Scroll + 1) & 0x07;
  Command(0xD3);
  Command(Scroll << 3);
}

// Plots a character; line = 0 to 7; column = 0 to 20
void PlotChar(char c, int line, int column) {
  column = column*6;
  Command(0xB0 + ((line + Scroll) & 0x07));
  Command(0x00 + (column & 0x0F)); // Column start low
  Command(0x10 + (column >> 4));   // Column start high
  for (uint8_t col = 0 ; col < 6; col++) {
    Data(pgm_read_byte(&CharMap[c-32][col]));
  }
}

// Prints a character, handling control characters
void Print(char c) {
  c = c & 0x7F; // Ignore top bit
  if (c >= 32) {
    PlotChar(c, Line, Column++);
    if (Column > 20) {
      Column = 0;
      if (Line == 7) ScrollDisplay(); else Line++;
    }
  }
  // Return character
  else if (c == 13) {
    Column = 0;
    if (Line == 7) ScrollDisplay(); else Line++;
  }
}
ssd1306_terminal.png
 
Сверху Снизу