• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

alexlaw

Member
К сожалению пока не получается.
Попробовал в Proteus, то же самое, что и в железе.
Не правильный ход мыслей.
Может у кого получится.
Скетч - Usart_1Wire.
Остальные работают правильно.
 

Вложения

nikolz

Well-known member
К сожалению пока не получается.
Попробовал в Proteus, то же самое, что и в железе.
Не правильный ход мыслей.
Может у кого получится.
Скетч - Usart_1Wire.
Остальные работают правильно.
Подсказка.
суть в том, что вам надо объединить два сигнала туда и обратно так, чтобы выход не закоротил вход при работе 1-wire в сторону UART
Классически это решается созданием на выходе третьего состояния (состояние большого сопротивления фактически разрыв цепи), когда сигнал идет в сторону UART
Если взять диод, то при подаче обратного напряжения его сопротивление станет большим- т е. диод и создаст третье состояние.
Как это сделать? Как включить диод чтобы создать такой режим?
Подумайте над этим.
 

alexlaw

Member
Получилось.
Код:
//http://microsin.net/programming/AVR/avr318-dallas-1-wire-master.html
//https://www.maximintegrated.com/en/app-notes/index.mvp/id/214
unsigned char temp;
unsigned int tmp;
uint8_t WireCRC;
byte Num[10] ={126,48,109,121,51,91,95,112,127,123};
int slaveSelect=14;
int din=6;
int clk=15;
// буфер данных
// 8 байт - CRC
// Если вычисленный CRC совпадает с прочитанным CRC, то
// данные были получены без ошибок
//7 байт - 0x10, 6 байт - 0x0C, 5 байт - 0xFF
byte bufData[9];
byte a,b,n;
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(din, OUTPUT);
  pinMode(clk, OUTPUT);
  pinMode(12, OUTPUT);
  digitalWrite(12,0);
sendCommand(12,1); //normal mode (default is shutdown mode)
sendCommand (15,0); //Display test off
sendCommand (10,6); //set medium intensity (range is 0-15)
sendCommand (11, 7); //7219 digit scan limit command
sendCommand (9, 0); //decode command, use standard 7-segment digits
clearDisp();
//---------------------
//CodeVisionAVR V2.05.0
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x06;
// USART Baud Rate: 115200
UBRRH=0x00;
UBRRL=0x03;
//---------------------
//digitalWrite(12,DetectPresence());
}

void loop() {
a=0;b=0;n=0; 
DetectPresence();// сброс шины 
Wire_Transmit(0xCC);// пропуск ROM
Wire_Transmit(0x44);//инициализация измерения
delay(900);  // пауза
DetectPresence();// сброс шины
Wire_Transmit(0xCC);// пропуск ROM
Wire_Transmit(0xBE);// чтение памяти датчика
for(int i = 0; i < 72; i++) { //чтение 9 байт памяти датчика      
     if (a==8) {
        bufData[n]=b;
        a=0;
        b=0;
        n++;       
     }
b |= (ReadBit()<<a);
a++;      
}
//вести подсчет CRC по алгоритму для всех байтов,
//включая последний байт контрольной суммы.
//если искажений не было, получится 0.
//для 8 байт crc равно 8 байту буфера 
WireCRC=OneWireCRC (8);
if (bufData[9]==WireCRC)digitalWrite(12,0); //OK
else digitalWrite(12,1);//ошибка crc
    if ((bufData[1]&128) != 0)//'-' отрицательная температура
    {          
      sendCommand (5, 1);
      tmp = ((unsigned char)bufData[1]<<8) | bufData[0];
      tmp = ~tmp + 1;
      bufData[0] = tmp;
      bufData[1] = tmp>>8; 
    }
temp = bufData[0]>>4 | bufData[1]<<4;
sendCommand (4, Num[temp/10]);
sendCommand (3, Num[temp % 10]);
//delay(2000);
////отладка-------------------
//disp(WireCRC,0);//расчетное crc
//delay(2000);
//disp(bufData[9],128); //crc полученное от датчика
delay(2000);
clearDisp();
//отладка-------------------
}
void clearDisp()
{
sendCommand (8, 0);
sendCommand (7, 0);
sendCommand (6, 0);
sendCommand (5, 0);
sendCommand (4, 1);
sendCommand (3, 1);
sendCommand (2, 99);
sendCommand (1, 78);//t*C  --*  
}
void sendCommand(byte cmd, byte data)
{
digitalWrite(slaveSelect, LOW); //chip select is active low
// передать старший байт
shiftOut(din, clk, MSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, MSBFIRST, data);
digitalWrite(slaveSelect,HIGH);
}
unsigned char TouchBit(unsigned char outValue)
{   
    // Place the output value in the UART transmit buffer, and wait
    // until it is received by the UART receiver.
    UDR = outValue;
    while(!(UCSRA & (1 << RXC)))
    {
    }
    // Set the UART Baud Rate back to 115200kbps when finished.
    // USART Baud Rate: 115200
    UBRRH=0x00;
    UBRRL=0x03;
    return UDR;
}
unsigned char DetectPresence()
{
    // Reset UART receiver to clear RXC register.
    UCSRB &= ~(1 << RXEN);
    UCSRB |= (1 << RXEN);   
    // Set UART Baud Rate to 9600 for Reset/Presence signalling.
    // USART Baud Rate: 9600 
    UBRRH=0x00;
    UBRRL=0x33;   
    // Return 0 if the value received matches the value sent.
    // return 1 else. (Presence detected)
    return (TouchBit(0xF0) != 0xF0);
}
void WriteBit1()
{
    TouchBit(0xff);
}
void WriteBit0()
{
    TouchBit(0x00);
}
void Wire_Transmit(unsigned int data)
{
for(int i = 0; i < 8; i++)
{
   if(data&0x01) WriteBit1();
      else WriteBit0();  
   data = data >> 1; // Следующий бит
}
}
unsigned char ReadBit(){
     // Return 1 if the value received matches the value sent.
     // Return 0 else. (A slave held the bus low).
     return (TouchBit(0xff) == 0xff);
}
uint8_t OneWireCRC (int bytes) {
  uint8_t crc = 0;
  for (int j=0; j<bytes; j++) {
    crc = crc ^ bufData[j];
    for (int i=0; i<8; i++) crc = crc>>1 ^ ((crc & 1) ? 0x8c : 0);
  }
  return crc;
}
//отладка-------------------
//1-lsb-младший бит,8-msb-старший бит
void disp(unsigned char data,unsigned char dot){
for(int i = 1; i < 9; i++) {
  if (i==8) sendCommand (i, Num[data & 0x01] | dot);
  else  sendCommand (i, Num[data & 0x01]);
  data = data >> 1; // Следующий бит 
} 
}
//отладка-------------------
 

alexlaw

Member
Тестирование кнопок
Button.png
Код:
//https://play.google.com/store/apps/details?id=com.peterhohsy.atmega_tutoriallite&hl=ru
#include <util/delay.h>
#define Keypad1_PORT    PORTB
#define Keypad1_DIR     DDRB
#define Keypad1_PIN     PINB

#define Segment1_PORT    PORTD
#define Segment1_DIR     DDRD
#define Segment1_PIN     PIND

#define KEYPAD_NO_PRESS  (unsigned char) 0xFF
#define KEY1_PRESS       (unsigned char) 0 
#define KEY2_PRESS       (unsigned char) 1 
#define KEY3_PRESS       (unsigned char) 2 
#define KEY4_PRESS       (unsigned char) 3 
#define KEY5_PRESS       (unsigned char) 4 
#define KEY6_PRESS       (unsigned char) 5 
#define KEY7_PRESS       (unsigned char) 6 
#define KEY8_PRESS       (unsigned char) 7 
#define KEY9_PRESS       (unsigned char) 8 
#define KEY10_PRESS      (unsigned char) 9 
#define KEY11_PRESS      (unsigned char) 10 
#define KEY12_PRESS      (unsigned char) 11 
#define KEY13_PRESS      (unsigned char) 12 
#define KEY14_PRESS      (unsigned char) 13 
#define KEY15_PRESS      (unsigned char) 14 
#define KEY16_PRESS      (unsigned char) 15

#define KEY_RELEASE   1
#define KEY_PRESS     0

unsigned char segment1[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; // 0~F
unsigned char Keypad1_Data  = 0;       
unsigned char Keypad1_State = KEY_RELEASE;
int key;
void setup() {
// Если  вывод  функционирует  как  вход, то
//при  установке  бита  PORTxn  в  1  подтягивающий  резистор 
//подключается между выводом микроконтроллера и шиной питания.
Keypad1_PORT=0xFF;// pullup
//Бит  DDxn  регистра  DDx  определяет  направление  передачи  данных
//через контакт ввода/вывода. Если этот бит установлен в 1, то nй вывод
//порта является выходом, если же сброшен в 0 — входом.
Keypad1_DIR=0x00;// input

//Если бит установлен в 1, на выводе устанавливается
//напряжение ВЫСОКОГО уровня.
Segment1_PORT=0x00;// low
//Бит  DDxn  регистра  DDxв установлен в 1, то nй вывод
//порта является выходом
//---------------
Segment1_DIR=0x7F;// output
Segment1_off();
}

void loop() {   
       key = Get_Keypad1_Press();   
       if (key !=KEYPAD_NO_PRESS)
       {   
            Segment1_ShowDigit(key & 0x0f);
       }
delay(100);
//Segment1_off();
}
// show hexadecimal 0 ~ F
void Segment1_ShowDigit(unsigned char hexadecimal)
{
      Segment1_PORT = segment1[ hexadecimal & 0x0f];
}
void Segment1_off()
{
      Segment1_PORT = 0x00;
}
// show pattern : 00 ~ FF
//     a
//    --
// f |  | b
//    -- g
// e |  | c
//    --
//    d
//  bit6 bit5 bit4 bit3 bit2 bit1 bit0
//    g   f    e    d    c    b    a
void Segment1_ShowPattern(unsigned char pattern) // 00-FF
{
    Segment1_PORT = pattern;
}
unsigned char Get_Keypad1_Press()
{
    unsigned char temp1 = 0xff;
    if (Keypad1_State == KEY_RELEASE)
    {
        // input | output
        Keypad1_DIR = 0x0F;      
        Keypad1_PORT = 0xF0;   
_delay_loop_2(8);
        switch (Keypad1_PIN & 0xF0)
        {
               case 0xE0 : temp1=0 ; break;
               case 0xD0 : temp1=1 ; break;
               case 0xB0 : temp1=2 ; break;
               case 0x70 : temp1=3; break;
               default : temp1=0xff; break;
         }
         if (temp1==0xff)
         {
             Keypad1_Data = KEYPAD_NO_PRESS;
             return KEYPAD_NO_PRESS;
         }
         Keypad1_Data = temp1 * 4;

        //  output | input
        Keypad1_DIR = 0xF0;      
        Keypad1_PORT = 0x0F;  
_delay_loop_2(8);
        switch (Keypad1_PIN & 0x0F)
        {
               case 0x0E : temp1=0 ; break;
               case 0x0D : temp1=1 ; break;
               case 0x0B : temp1=2 ; break;
               case 0x07 : temp1=3;  break;
               default : temp1=0xff; break;
        }
        if (temp1==0xff)
        {
            Keypad1_Data = KEYPAD_NO_PRESS;
            return KEYPAD_NO_PRESS;
        }
        else
        {
            delay(25);
            Keypad1_Data = Keypad1_Data + temp1;
            Keypad1_State = KEY_PRESS;
            return  KEYPAD_NO_PRESS ;
        }
      }
      else
      {
          Keypad1_DIR = 0x0F;  
          Keypad1_PORT = 0xF0; 
_delay_loop_2(8);
          switch (Keypad1_PIN & 0xF0)
          {
              case 0xE0 : temp1=0 ; break;
              case 0xD0 : temp1=1 ; break;
              case 0xB0 : temp1=2 ; break;
              case 0x70 : temp1=3; break;
              default : temp1=0xff; break;
          }
          if (temp1 != 0xff)
              return KEYPAD_NO_PRESS;
          else
          {
              Keypad1_State = KEY_RELEASE;
              return Keypad1_Data;
          }    
     }
}
 

Вложения

nikolz

Well-known member
Задачка.
Все кнопки можно подключить к одному пину,
если сразу не получится, то максимум к двум.
число кнопок -любое.
подумайте над этим
 

alexlaw

Member
Задачка.
Все кнопки можно подключить к одному пину,
если сразу не получится, то максимум к двум.
число кнопок -любое.
подумайте над этим
У Attiny2313 отсутствует Аналого\цифровой преобразователь.
А с помощью аналогового компаратора, мне кажется слишком трудоемко и не эффективно.
В общем, пока не вижу как подключить много кнопок к одному пину. Если знаете подскажите куда двигаться.
PS Памяти всего 2 кб, поэтому экономить пины мне кажется нецелесообразно.
 

nikolz

Well-known member
я разве указал что это аналоговый пин?
К аналоговому и д... сможет
Задача подключить бесконечное число кнопок к любому пину или двум которые являются бинарными PIO.
Подумайте над этим
 

alexlaw

Member
Здравствуйте.
Кнопки пока решил отложить - не определился с концепцией.
То ли использовать дополнительный сдвиговый регистр, то ли измерять время
зарядки конденсатора. Ну да ладно.
Жду когда придут часы реального времени DS1302. А пока эмулирую в протеусе.
Так вот если подключить виртуальный осциллограф к схеме, то время считывается
правильно, если его отключить, то не правильно.
В чем может быть причина?
PS Меня интересует именно функции shiftOut и shiftIn,
поэтому прошу не переводить вопрос на другие возможности (другая эмуляция SPI и т.п.)
 

Вложения

nikolz

Well-known member
Здравствуйте.
Кнопки пока решил отложить - не определился с концепцией.
То ли использовать дополнительный сдвиговый регистр, то ли измерять время
зарядки конденсатора. Ну да ладно.
Жду когда придут часы реального времени DS1302. А пока эмулирую в протеусе.
Так вот если подключить виртуальный осциллограф к схеме, то время считывается
правильно, если его отключить, то не правильно.
В чем может быть причина?
PS Меня интересует именно функции shiftOut и shiftIn,
поэтому прошу не переводить вопрос на другие возможности (другая эмуляция SPI и т.п.)
вопрос не понятный.
В протеусе подключаете?
Посмотрите какие параметры этого осциллографа
В этом и есть разница - с ним и без него.
 

alexlaw

Member
Поставил диод на линию DIN на max7219 и все заработало.
DS1302_MAX7219.png
Код:
//-----------------------------------------------------------------------------
/*                                   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    */
//-----------------------------------------------------------------------------                                    
unsigned char temp;
unsigned char prevtemp=100;
unsigned int tmp;
             //0  1  2   3   4  5  6  7  8   9   A    B  C  D  E  F
byte Num[] ={126,48,109,121,51,91,95,112,127,123,119,31,78,61,79,71};
uint8_t TimeBytes[7];// = {0,0,0,0,0,0,0};
int slaveSelect=14;
int din=6;
int clk=15;
// буфер данных
// 8 байт - CRC
// Если вычисленный CRC совпадает с прочитанным CRC, то
// данные были получены без ошибок
//7 байт - 0x10, 6 байт - 0x0C, 5 байт - 0xFF
byte bufData[9];
byte a,b,n;
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(din, OUTPUT);
  pinMode(clk, OUTPUT);
sendCommand7219(12,1); //normal mode (default is shutdown mode)
sendCommand7219 (15,0); //Display test off
sendCommand7219 (10,6); //set medium intensity (range is 0-15)
sendCommand7219 (11, 7); //7219 digit scan limit command
sendCommand7219 (9, 0); //decode command, use standard 7-segment digits
  //УСТАНОВИТЬ ВРЕМЯ 30.11.1994 23 часа 45 мин 30 сек
  sendCommand1302(0x86, 0x30);
  sendCommand1302(0x88, 0x11);
  sendCommand1302(0x8C, 0x94);
//  sendCommand1302(0x84, 0x23);
//  sendCommand1302(0x82, 0x45);
//  sendCommand1302(0x80, 0x30);
//  sendCommand1302(0x8A, 0x01);//день пн
//---------------------
//CodeVisionAVR V2.05.0
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x06;
// USART Baud Rate: 115200
UBRRH=0x00;
UBRRL=0x03;
//---------------------
//digitalWrite(12,DetectPresence());
}

void loop() {
a=0;b=0;n=0; 
DetectPresence();// сброс шины 
Wire_Transmit(0xCC);// пропуск ROM
Wire_Transmit(0x44);//инициализация измерения
delay(900);  // пауза
DetectPresence();// сброс шины
Wire_Transmit(0xCC);// пропуск ROM
Wire_Transmit(0xBE);// чтение памяти датчика
for(int i = 0; i < 72; i++) { //чтение 9 байт памяти датчика      
     if (a==8) {
        bufData[n]=b;
        a=0;
        b=0;
        n++;       
     }
b |= (ReadBit()<<a);
a++;      
}

    if ((bufData[1]&128) != 0)//'-'
    {          
      sendCommand7219 (4, 1);
      tmp = ((unsigned char)bufData[1]<<8) | bufData[0];
      tmp = ~tmp + 1;
      bufData[0] = tmp;
      bufData[1] = tmp>>8; 
    } else sendCommand7219 (4, 0);
temp = bufData[0]>>4 | bufData[1]<<4;
sendCommand7219 (3, Num[temp/10]);
sendCommand7219 (2, Num[temp % 10]);
sendCommand7219 (1, 99);
//sendCommand7219 (1, 78);
data1302();
ViewTime(8, TimeBytes[2]);//часы
ViewTime(6, TimeBytes[1]);//минуты
delay(60000);
}

void sendCommand7219(byte cmd, byte data)
{
digitalWrite(slaveSelect, LOW); //chip select is active low
// передать старший байт
shiftOut(din, clk, MSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, MSBFIRST, data);
digitalWrite(slaveSelect,HIGH);
}
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]=shiftIn(din, clk, LSBFIRST);
}
digitalWrite(slaveSelect,LOW);
pinMode(din, OUTPUT);
}
unsigned char TouchBit(unsigned char outValue)
{   
    // Place the output value in the UART transmit buffer, and wait
    // until it is received by the UART receiver.
    UDR = outValue;
    while(!(UCSRA & (1 << RXC)))
    {
    }
    // Set the UART Baud Rate back to 115200kbps when finished.
    // USART Baud Rate: 115200
    UBRRH=0x00;
    UBRRL=0x03;
    return UDR;
}
unsigned char DetectPresence()
{
    // Reset UART receiver to clear RXC register.
    UCSRB &= ~(1 << RXEN);
    UCSRB |= (1 << RXEN);   
    // Set UART Baud Rate to 9600 for Reset/Presence signalling.
    // USART Baud Rate: 9600 
    UBRRH=0x00;
    UBRRL=0x33;   
    // Return 0 if the value received matches the value sent.
    // return 1 else. (Presence detected)
    return (TouchBit(0xF0) != 0xF0);
}
void WriteBit1()
{
    TouchBit(0xff);
}
void WriteBit0()
{
    TouchBit(0x00);
}
void Wire_Transmit(unsigned int data)
{
for(int i = 0; i < 8; i++)
{
   if(data&0x01) WriteBit1();
      else WriteBit0();  
   data = data >> 1; // Следующий бит
}
}
unsigned char ReadBit(){
     // Return 1 if the value received matches the value sent.
     // Return 0 else. (A slave held the bus low).
     return (TouchBit(0xff) == 0xff);
}

void ViewTime(byte high_place, byte data)
{
   sendCommand7219 (high_place, Num[(data & 0xF0) >> 4]);
   sendCommand7219 (high_place-1, Num[data & 0x0F]);
}
 

alexlaw

Member
Несколько ссылок для дальнейшего изучения или я бы назвал "используемая литература"

Интересный проект
 

alexlaw

Member
В "железе" с RTC 1302 пришлось немного подкорректировать.
Выкинул диод и SHIFTIN
IMG_20190709_145543.jpg
Схема
DS1302_MAX7219_1.png
Код:
//-----------------------------------------------------------------------------
/*                                   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    */
//-----------------------------------------------------------------------------                                   
int slaveSelect=14;//PB5
int din=6;//PD4
int clk=15;//PB6
uint8_t TimeBytes[] ={0x41,0x42,0x43,0x44,'E','\n','\r'};
byte Num[] ={126,48,109,121,51,91,95,112,127,123,119,31,78,61,79,71};

void setup() {
  pinMode(clk, OUTPUT);//7 - 15 PB6 СИНИЙ
  pinMode(din, OUTPUT);//6 - 6 PD4 ЗЕЛЕНЫЙ
  pinMode(slaveSelect, OUTPUT);//5 - 14 PB5 ЖЕЛТЫЙ
sendCommand7219(12,1); //normal mode (default is shutdown mode)
sendCommand7219 (15,0); //Display test off
sendCommand7219 (10,6); //set medium intensity (range is 0-15)
sendCommand7219 (11, 7); //7219 digit scan limit command
sendCommand7219 (9, 0); //decode command, use standard 7-segment digits
sendCommand7219 (8, 0);
sendCommand7219 (7, 61);
sendCommand7219 (6, 91);
sendCommand7219 (5, 1);
sendCommand7219 (4, 48);
sendCommand7219 (3, 121);
sendCommand7219 (2, 126);
sendCommand7219 (1, 109);
delay(1000);
//  //УСТАНОВИТЬ ВРЕМЯ 30.11.94 23 часа 45 мин 00 сек
  sendCommand1302(0x86, 0x30);//день
  sendCommand1302(0x88, 0x11);//месяц
  sendCommand1302(0x8C, 0x94);//год
  sendCommand1302(0x84, 0x23);//час
  sendCommand1302(0x82, 0x45);//мин
  sendCommand1302(0x80, 0x00);//сек
  sendCommand1302(0x8A, 0x01);//день недели пн

}

void loop() {
data1302();
ViewTime(8, TimeBytes[2]);//часы
sendCommand7219 (6, 1);
ViewTime(5, TimeBytes[1]);//минуты
sendCommand7219 (3, 1);
ViewTime(2, TimeBytes[0]);//секунды
delay(800);
}
void sendCommand7219(byte cmd, byte data)
{
digitalWrite(slaveSelect, LOW); //chip select is active low
// передать старший байт
shiftOut(din, clk, MSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, MSBFIRST, data);
digitalWrite(slaveSelect,HIGH);
}
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 ViewTime(byte high_place, byte data)
{
   sendCommand7219 (high_place, Num[(data & 0xF0) >> 4]);
   sendCommand7219 (high_place-1, Num[data & 0x0F]);
}
Все работает :)
 

nikolz

Well-known member
В "железе" с RTC 1302 пришлось немного подкорректировать.
Выкинул диод и SHIFTIN
Посмотреть вложение 7620
Все работает :)
А как вам такая схема

--------------------------
теперь для сравнения нарисуйте тоже самое на STM8L151
8-bit ultra-low-power MCU, up to 32 KB Flash, 1 KB Data EEPROM, RTC, LCD, timers, USART, I2C, SPI, ADC, DAC, comparators.
получится и дешевле и проще и меньше кушает и встроенный драйвер индикатора.
 

alexlaw

Member
несомненно лучше. Но ...
ATTINY2313 хорош для начинающих, таких как я.
А STM8L151 это уже следующий этап.
К тому же я хотел использовать для программирования среду Arduino IDE, т.к. код в ней можно менять буквально на лету, что хорошо для наглядности и отладки.
А пока работа с RAM RTC 1302
Код:
//-----------------------------------------------------------------------------
/*                                   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    */
//-----------------------------------------------------------------------------                                    
int slaveSelect=14;//PB5
int din=6;//PD4
int clk=15;//PB6
uint8_t TimeBytes[] ={0x41,0x42,0x43,0x44,'E','\n','\r'};
byte Num[] ={126,48,109,121,51,91,95,112,127,123,119,31,78,61,79,71};
byte ds1302[] ={0,61,91,1,48,121,126,109};
uint8_t ReadBytes[8];
void setup() {
  pinMode(clk, OUTPUT);//7 - 15 PB6 СИНИЙ
  pinMode(din, OUTPUT);//6 - 6 PD4 ЗЕЛЕНЫЙ
  pinMode(slaveSelect, OUTPUT);//5 - 14 PB5 ЖЕЛТЫЙ
sendCommand7219(12,1); //normal mode (default is shutdown mode)
sendCommand7219 (15,0); //Display test off
sendCommand7219 (10,6); //set medium intensity (range is 0-15)
sendCommand7219 (11, 7); //7219 digit scan limit command
sendCommand7219 (9, 0); //decode command, use standard 7-segment digits

sendCommand7219 (0x0C,0); //Display  off
delay(100);
//УСТАНОВИТЬ ВРЕМЯ
  sendCommand1302(0x86, 0x10);//день
  sendCommand1302(0x88, 0x07);//месяц
  sendCommand1302(0x8C, 0x19);//год
  sendCommand1302(0x84, 0x12);//час
  sendCommand1302(0x82, 0x25);//мин
  sendCommand1302(0x80, 0x00);//сек
  sendCommand1302(0x8A, 0x03);//день недели
    for (int i = 0; i < 8; ++i)
  {   
    sendCommand1302((i * 2) + 192, ds1302[i]);//запись 8 байт в RAM
  }
  delay(1000);
  //чтение 8 байт из RAM
      for (int i = 0; i < 8; ++i)
  {   
    digitalWrite(slaveSelect,HIGH); //chip select is active HIGH
    shiftOut(din, clk, LSBFIRST, (i * 2) + 193);
    pinMode(din, INPUT);
    ReadBytes[i]=readByte();
    digitalWrite(slaveSelect,LOW);
    pinMode(din, OUTPUT);
  } 
        for (int i = 1; i < 9; ++i)
  {
    sendCommand7219 (i, ReadBytes[8-i]);   
  }
  sendCommand7219 (0x0C,1); //Display  on
  delay(2000);
}

void loop() {
data1302();
ViewTime(8, TimeBytes[2]);//часы
sendCommand7219 (6, TimeBytes[0]&0x01);
ViewTime(5, TimeBytes[1]);//минуты
sendCommand7219 (3, !(TimeBytes[0]&0x01));
ViewTime(2, TimeBytes[0]);//секунды
delay(1000);
}
void sendCommand7219(byte cmd, byte data)
{
digitalWrite(slaveSelect, LOW); //chip select is active low
// передать старший байт
shiftOut(din, clk, MSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, MSBFIRST, data);
digitalWrite(slaveSelect,HIGH);
}
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 ViewTime(byte high_place, byte data)
{
   sendCommand7219 (high_place, Num[(data & 0xF0) >> 4]);
   sendCommand7219 (high_place-1, Num[data & 0x0F]);
}
 

fps

Active member
Задача подключить бесконечное число кнопок к любому пину или двум которые являются бинарными PIO.
Интересная задача.
Надеюсь она не подразумевает дополнительных микросхем и/или RC цепочек?
Тогда не могу придумать. Нужна подсказка.
 

alexlaw

Member
Добавил кнопку для установки часов (время настраивается заранее, кнопка для синхронизации программного и реального времени)
DS1302.png
 

Вложения

nikolz

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

alexlaw

Member
да и зачем он если есть дисплей
Светодиоды для наглядности.
Сработает прерывание при наж кнопок, светодиод мигнет.
Продолжаю изучать кнопки
DS1302-led.png
Код:
//-----------------------------------------------------------------------------
/*                                   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    */
//-----------------------------------------------------------------------------                                    
//https://www.myrobot.ru/stepbystep/pr_mcports.php
int slaveSelect=14;//PB5
int din=6;//PD4
int clk=15;//PB6
uint8_t TimeBytes[] ={0x41,0x42,0x43,0x44,'E','\n','\r'};
byte Num[] ={126,48,109,121,51,91,95,112,127,123,119,31,78,61,79,71};
byte ds1302[] ={0,61,91,1,48,121,126,109};
boolean b = false;
void setup() {
//pb0 pb1 pb2 кнопки
//pb3 pb4 светодиод  
PORTB |= (1 << 0) | (1 << 1 ) | (1 << 2);// Set bits - pullup
DDRB &= ~((1 << 0)  | (1 << 1)  | (1 << 2));// 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) | (1 << 2);// Set bits -прерывание по изменению состояния вывода 0 или 1  или 2 - PCINT

  pinMode(clk, OUTPUT);//7 - 15 PB6 СИНИЙ
  pinMode(din, OUTPUT);//6 - 6 PD4 ЗЕЛЕНЫЙ
  pinMode(slaveSelect, OUTPUT);//5 - 14 PB5 ЖЕЛТЫЙ
sendCommand7219(12,1); //normal mode (default is shutdown mode)
sendCommand7219 (15,0); //Display test off
sendCommand7219 (10,6); //set medium intensity (range is 0-15)
sendCommand7219 (11, 7); //7219 digit scan limit command
sendCommand7219 (9, 0); //decode command, use standard 7-segment digits
        for (int i = 1; i < 9; ++i)
  {
    sendCommand7219 (i, ds1302[8-i]);   
  }
  delay(2000);
}

void loop() {
if (b) SetTime(); 
data1302();
ViewTime(8, TimeBytes[2]);//часы
sendCommand7219 (6, TimeBytes[0]&0x01);
ViewTime(5, TimeBytes[1]);//минуты
sendCommand7219 (3, !(TimeBytes[0]&0x01));
ViewTime(2, TimeBytes[0]);//секунды
delay(1000);
}
void sendCommand7219(byte cmd, byte data)
{
digitalWrite(slaveSelect, LOW); //chip select is active low
// передать старший байт
shiftOut(din, clk, MSBFIRST, cmd);
// передать младший байт
shiftOut(din, clk, MSBFIRST, data);
digitalWrite(slaveSelect,HIGH);
}
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 ViewTime(byte high_place, byte data)
{
   sendCommand7219 (high_place, Num[(data & 0xF0) >> 4]);
   sendCommand7219 (high_place-1, Num[data & 0x0F]);
}
void SetTime()
{
//УСТАНОВИТЬ ВРЕМЯ
  sendCommand1302(0x86, 0x10);//день
  sendCommand1302(0x88, 0x07);//месяц
  sendCommand1302(0x8C, 0x19);//год
  sendCommand1302(0x84, 0x12);//час
  sendCommand1302(0x82, 0x25);//мин
  sendCommand1302(0x80, 0x00);//сек
  sendCommand1302(0x8A, 0x03);//день недели
  b = false;
}
ISR(PCINT_vect) {
  //наж кн pb0
  if (!(PINB & 0x01)) PORTB |= (1 << 3);// Set bits - high pb3
  else PORTB &= ~(1 << 3);// Clear bit
  //наж кн pb1
  if (!(PINB>>1 & 0x01)) PORTB |= (1 << 4);// Set bits - high pb4
  else PORTB &= ~(1 << 4);// Clear bit
  //наж кн pb2
  if (!(PINB>>2 & 0x01)) {PORTB |= (1 << 3) | (1 << 4);// Set bits - high pb3 pb4
       b = true;
  }
}
nikolz - вы ничего не рассказали про ваш метод работы с кнопками.
Или это секрет?
 
Сверху Снизу