Arduino UNO + ATmega16, SPI и I2C

Нет ответов
arz_serg
Offline
Зарегистрирован: 05.04.2019

Доброго времени суток, господа форумчане. Приношу свои извинения за много букв, чтобы описать проблему - писать надо много, но постараюсь максимально сжато.

Имеются уличные часы с 4-х разрядным светодиодными индикатором, на подобии тех, что частенько можно увидеть на школах, проходных заводов и т.п. Каждый разряд состоит из 24 сегментов и управляется микросхемой ATmega16. Эти 4 атмеги в свою очередь получали команды о выводе цифр от ещё одной ATmega16. Т.е. итого было пять атмег: одна основная и 4 дочерние.

Во время грозы сгорела основная атмега и часы были отданы товарищу-электронщику "на запчасти". Но он решил попытаться их восстановить. Рассмотрев различные варианты, остановились на том, что сгоревшую атмегу заменяем на ардуину, а в атмеги, управляющие разрядами - заливаем новую прошивку.

Изначально я даже не имел представления как прошивать ATmega16 через ардуино. Но с помощью этого видео: https://www.youtube.com/watch?v=P3CYDXBiIzM всё получилось.

Написал программу для атмег-разрядов, чтобы они перебирали цифры, написал программу для "головной ардуины", чтобы она считала время и разбивала его на 4 разряда. Оставалось дело за малым - отправлять эти цифры по SPI на дочерние платки. И вот тут меня ждало фиаско.

Кое-как, вписал я кусок кода для отправки/принятия данных по SPI . Писал не понимая чего я пишу, но с ардуины на ардуину оно заработало, а с ардуины на атмегу16 - нет. Хотел посмотреть что там принимает атмега16, подключил к ней LCD дисплейчик 1602 - на ардуине он работает, а на атмеге снова нет.

Собственно закрались подозрения, что используемые библиотеки #include <Wire.h> и #include <LiquidCrystal_I2C.h> - ссылаются где-то глубоко внутри себя на пины ардуины. Так ли это и если так, то как их переназначить, чтобы они соответствовали пинам атмеги16?

----------------------------------------------------

Прилагаю код, который зашивается в "основную" ардуину:

#define SS_m 10                          // Пин отправки младшего разряда минут
#define SS_M 9                           // Пин отправки старшего разряда минут
#define SS_h 8                           // Пин отправки младшего разряда часов
#define SS_H 7                           // Пин отправки старшего разряда часов

#define tperiod 1                          // Периодичность считывания и отправки времени (сек)

#include <SPI.h>                            // Подключаем протокол обмена данными
#include <Wire.h>                           // Подключаем библиотеку Wire                           
#include <TimeLib.h>                        // Подключаем библиотеку TimeLib
#include <DS1307RTC.h>                      // Подключаем библиотеку DS1307RTC


char HOUR,MIN,SEC,H,h,M,m,S,s;              // Переменные для получения времени и разбития по разрядам
tmElements_t tm;                            // Создаем объект tm для чтения времени

// ---------- УСТАНОВКА ПАРАМЕТРОВ SPI-MASTER ---------- \\

void SPI_Setup()
{
   SPI.setDataMode(SPI_MODE0);
   SPI.setBitOrder(MSBFIRST);
   SPI.setClockDivider(SPI_CLOCK_DIV4);
   SPI.begin();
   pinMode(SS_m,OUTPUT);
   pinMode(SS_M,OUTPUT);
   pinMode(SS_h,OUTPUT);
   pinMode(SS_H,OUTPUT);
   digitalWrite(SS_m,HIGH);
   digitalWrite(SS_M,HIGH);
   digitalWrite(SS_h,HIGH);
   digitalWrite(SS_H,HIGH);
}

void setup() {

  SPI_Setup();
  Serial.begin(9600);
  
  delay(200);
  
}

void loop() {

// tmElements_t tm;                            // Создаем объект tm для чтения времени

 if (millis() % (tperiod * 1000) == 0) {
  RTC.read(tm);                   // Считываем время в объект tm
  HOUR = tm.Hour;                 // Записываем в переменную HOUR часы
  MIN = tm.Minute;                // Записываем в переменную MIN минуты
  SEC = tm.Second;

  H = HOUR / 10;                  // Выделяем старший разряд из часов
  h = HOUR % 10;                  // Выделяем младший разряд из часов
  M = MIN / 10;                   // Выделяем старший разряд из минут
  m = MIN % 10;                   // Выделяем младшиый разряд из минут
  S = SEC / 10;
  s = SEC % 10;

  Serial.print(H,DEC); Serial.print(h,DEC); Serial.print(" : "); Serial.print(M,DEC); Serial.print(m,DEC); Serial.print(" : "); Serial.print(S,DEC); Serial.println(s,DEC);
  digitalWrite(SS_H,LOW);         // Начинаем передачу в сегмент старшего разряда часов
  SPI.transfer(H);                // Отправляем старший разряд часов
  digitalWrite(SS_H,HIGH);        // Завершаем передачу в сегмент старшего разряда часов
  digitalWrite(SS_h,LOW);         // Начинаем передачу в сегмент младшего разряда часов
  SPI.transfer(h);                // Отправляем младший разряд часов
  digitalWrite(SS_h,HIGH);        // Завершаем передачу в сегмент младшего разряда часов
  digitalWrite(SS_M,LOW);         // Начинаем передачу в сегмент старшего разряда минут
  SPI.transfer(M);                // Отправляем старший разряд минут
  digitalWrite(SS_M,HIGH);        // Завершаем передачу в сегмент старшего разряда минут
  digitalWrite(SS_m,LOW);         // Начинаем передачу в сегмент младшего разряда минут
  SPI.transfer(m);                // Отправляем младший разряд минут
  digitalWrite(SS_m,HIGH);        // Завершаем передачу в сегмент младшего разряда минут
 } 
  //delay(500);

}

----------------------------------------------------

...и код, который разливается по "дочерним" атмегам:

#define SS_PIN 11                // Пин получения данных (цифра для вывода)

#define D0 0          
#define D1 1
#define D2 2
#define D3 3
#define D4 4
#define D5 5
#define D6 6
#define D7 7
#define D16 16
#define D17 17
#define D18 18
#define D19 19
#define D20 20
#define D21 21
#define D22 22
#define D23 23

#include <SPI.h>

char LNUM , NUM;                              // Переменные прошлая цифра , текущая цифра

void SPI_Setup()                              // Установка параметров обмена
{
   SPI.setDataMode(SPI_MODE0);
   SPI.setBitOrder(MSBFIRST);
   SPI.setClockDivider(SPI_CLOCK_DIV4);
   pinMode(MISO, OUTPUT);
   SPCR |= _BV(SPE); 
}   

byte SPI_read()                               // Процедура получения данных от Master
{
 if (digitalRead(SS_PIN) == LOW) 
   while(!(SPSR & (1<<SPIF)));
 return SPDR; 
}

void DRAWS(char num)                                                          // Процедура вывода цифр в статическом режиме
{
  digitalWrite(A0,LOW); digitalWrite(A1,LOW); digitalWrite(A2,LOW);           // Выключаем индикатор
  digitalWrite(A3,LOW); digitalWrite(A4,LOW); digitalWrite(A5,LOW);           // Выключаем индикатор
  digitalWrite(A6,LOW); digitalWrite(A7,LOW); digitalWrite(D0,LOW);           // Выключаем индикатор
  digitalWrite(D2,LOW); digitalWrite(D3,LOW); digitalWrite(D4,LOW);           // Выключаем индикатор 
  digitalWrite(D5,LOW); digitalWrite(D6,LOW); digitalWrite(D7,LOW);           // Выключаем индикатор 
  digitalWrite(D16,LOW); digitalWrite(D17,LOW); digitalWrite(D18,LOW);        // Выключаем индикатор
  digitalWrite(D19,LOW); digitalWrite(D20,LOW); digitalWrite(D21,LOW);        // Выключаем индикатор
  digitalWrite(D22,LOW); digitalWrite(D23,LOW); digitalWrite(D1,LOW);         // Выключаем индикатор

  switch (num) {                                                                          // Маски вывода цифр (-1 = выкл.)
  
    case 1: digitalWrite(D0,HIGH); digitalWrite(D1,HIGH); 
            digitalWrite(D3,HIGH); digitalWrite(D4,HIGH); digitalWrite(D7,HIGH);
            digitalWrite(D16,HIGH); digitalWrite(D20,HIGH); digitalWrite(D19,HIGH);
            digitalWrite(D18,HIGH); break;
  
    case 2: digitalWrite(A1,HIGH); digitalWrite(D1,HIGH); digitalWrite(D0,HIGH);
            digitalWrite(D3,HIGH); digitalWrite(D4,HIGH); digitalWrite(D5,HIGH);
            digitalWrite(D6,HIGH); digitalWrite(D1,HIGH); digitalWrite(A6,HIGH);
            digitalWrite(A7,HIGH); digitalWrite(D22,HIGH); digitalWrite(D21,HIGH);
            digitalWrite(D19,HIGH); digitalWrite(D18,HIGH); break;
  
    case 3: digitalWrite(A1,HIGH); digitalWrite(D1,HIGH); digitalWrite(D0,HIGH);
            digitalWrite(D3,HIGH); digitalWrite(D4,HIGH); digitalWrite(D5,HIGH);
            digitalWrite(D6,HIGH); digitalWrite(D17,HIGH); digitalWrite(D16,HIGH);
            digitalWrite(D20,HIGH); digitalWrite(D19,HIGH); digitalWrite(D21,HIGH); break;
  
    case 4: digitalWrite(A0,HIGH); digitalWrite(A3,HIGH); digitalWrite(A4,HIGH);
            digitalWrite(A6,HIGH); digitalWrite(D6,HIGH);
            digitalWrite(D0,HIGH); digitalWrite(D3,HIGH); digitalWrite(D4,HIGH);
            digitalWrite(D7,HIGH); digitalWrite(D16,HIGH); digitalWrite(D20,HIGH);
            digitalWrite(D19,HIGH); digitalWrite(D18,HIGH); break;
  
    case 5: digitalWrite(D1,HIGH); digitalWrite(A1,HIGH); digitalWrite(A0,HIGH);
            digitalWrite(A3,HIGH); digitalWrite(A4,HIGH); 
            digitalWrite(A6,HIGH); digitalWrite(D6,HIGH); digitalWrite(D17,HIGH);
            digitalWrite(D16,HIGH); digitalWrite(D20,HIGH); digitalWrite(D19,HIGH);
            digitalWrite(D21,HIGH); break;
  
    case 6: digitalWrite(D1,HIGH); digitalWrite(A1,HIGH); digitalWrite(A2,HIGH);
            digitalWrite(A3,HIGH); digitalWrite(A4,HIGH); digitalWrite(D23,HIGH);
            digitalWrite(D22,HIGH); digitalWrite(D21,HIGH); digitalWrite(D19,HIGH);
            digitalWrite(D20,HIGH); digitalWrite(D16,HIGH); digitalWrite(D17,HIGH);
            digitalWrite(D6,HIGH); digitalWrite(A6,HIGH); break;
  
    case 7: digitalWrite(A2,HIGH); digitalWrite(A1,HIGH); digitalWrite(D1,HIGH);
            digitalWrite(D0,HIGH); digitalWrite(D3,HIGH); digitalWrite(D4,HIGH);
            digitalWrite(D7,HIGH); digitalWrite(D16,HIGH); digitalWrite(D20,HIGH);
            digitalWrite(D19,HIGH); digitalWrite(D18,HIGH); break;
  
    case 8: digitalWrite(A1,HIGH); digitalWrite(A2,HIGH);
            digitalWrite(A3,HIGH); digitalWrite(A4,HIGH); digitalWrite(A5,HIGH);
            digitalWrite(A6,HIGH); digitalWrite(A7,HIGH); digitalWrite(D0,HIGH);
            digitalWrite(D2,HIGH); digitalWrite(D3,HIGH); digitalWrite(D4,HIGH);
            digitalWrite(D5,HIGH); digitalWrite(D6,HIGH); digitalWrite(D1,HIGH);
            digitalWrite(D16,HIGH); digitalWrite(D17,HIGH); 
            digitalWrite(D19,HIGH); digitalWrite(D20,HIGH); digitalWrite(D21,HIGH);
            digitalWrite(D22,HIGH); break;
  
    case 9: digitalWrite(A1,HIGH); digitalWrite(A2,HIGH);
            digitalWrite(A3,HIGH); digitalWrite(A4,HIGH); digitalWrite(A5,HIGH);
            digitalWrite(A6,HIGH); digitalWrite(A5,HIGH); digitalWrite(D0,HIGH);
            digitalWrite(D2,HIGH); digitalWrite(D3,HIGH); digitalWrite(D4,HIGH);
            digitalWrite(D5,HIGH); digitalWrite(D6,HIGH); digitalWrite(D7,HIGH); 
            digitalWrite(D16,HIGH); digitalWrite(D17,HIGH); digitalWrite(D1,HIGH);
            digitalWrite(D19,HIGH); digitalWrite(D20,HIGH); digitalWrite(D21,HIGH);
            break;
  
    case 0: digitalWrite(A1,HIGH); digitalWrite(A2,HIGH);
            digitalWrite(A3,HIGH); digitalWrite(A4,HIGH); 
            digitalWrite(D0,HIGH); digitalWrite(D1,HIGH);
            digitalWrite(D2,HIGH); digitalWrite(D3,HIGH); digitalWrite(D4,HIGH);
            digitalWrite(D7,HIGH);
            digitalWrite(D16,HIGH); 
            digitalWrite(D19,HIGH); digitalWrite(D20,HIGH); digitalWrite(D21,HIGH);
            digitalWrite(D22,HIGH); digitalWrite(D23,HIGH); break;
  
    case -1: digitalWrite(A0,LOW); digitalWrite(A1,LOW); digitalWrite(A2,LOW);
             digitalWrite(A3,LOW); digitalWrite(A4,LOW); digitalWrite(A5,LOW);
             digitalWrite(A6,LOW); digitalWrite(A7,LOW); digitalWrite(D0,LOW);
             digitalWrite(D2,LOW); digitalWrite(D3,LOW); digitalWrite(D4,LOW);
             digitalWrite(D5,LOW); digitalWrite(D6,LOW); digitalWrite(D7,LOW);
             digitalWrite(D16,LOW); digitalWrite(D17,LOW); digitalWrite(D18,LOW);
             digitalWrite(D19,LOW); digitalWrite(D20,LOW); digitalWrite(D21,LOW);
             digitalWrite(D22,LOW); digitalWrite(D23,LOW); break;       
  }      
 }           
            
            
void setup() {                
 
  SPI_Setup();
//  Serial.begin(9600); 
  
  pinMode(D0, OUTPUT);     
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);
  pinMode(D5, OUTPUT);
  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
  pinMode(D16, OUTPUT);
  pinMode(D17, OUTPUT);
  pinMode(D18, OUTPUT);
  pinMode(D19, OUTPUT);
  pinMode(D20, OUTPUT);
  pinMode(D21, OUTPUT);
  pinMode(D22, OUTPUT);
  pinMode(D23, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  pinMode(A6, OUTPUT);
  pinMode(A7, OUTPUT);
  
  digitalWrite(A0,LOW); digitalWrite(A1,LOW); digitalWrite(A2,LOW);
  digitalWrite(A3,LOW); digitalWrite(A4,LOW); digitalWrite(A5,LOW);
  digitalWrite(A6,LOW); digitalWrite(A7,LOW); digitalWrite(D0,LOW);
  digitalWrite(D2,LOW); digitalWrite(D3,LOW); digitalWrite(D4,LOW);
  digitalWrite(D5,LOW); digitalWrite(D6,LOW); digitalWrite(D7,LOW);
  digitalWrite(D16,LOW); digitalWrite(D17,LOW); digitalWrite(D18,LOW);
  digitalWrite(D19,LOW); digitalWrite(D20,LOW); digitalWrite(D21,LOW);
  digitalWrite(D22,LOW); digitalWrite(D23,LOW); 
  
  LNUM = -1;
  delay(250);

}

void loop()
{
 delay(100);
 NUM = SPI_read();                          // Получаем цифру
 
 if (NUM != LNUM) {                         // Если полученная цифра отличается
  LNUM = NUM;                               // от нарисованной, то записываем её в LNUM
  DRAWS(NUM);                               // и выводим на индикатор 
//  Serial.println(NUM,DEC);
 }
  
// if (NUM < 9) NUM++; else NUM = -1;              // Перебираем цифры
// delay(2500); 
// DRAWS(NUM);

//  DRAWS(10);

}

----------------------------------------------------

Простенький кодик и библиотека для LCD-Дисплея по I2C, которые работают на ардуине, но не работают на атмеге были взяты отсюда: https://lesson.iarduino.ru/page/urok-4-podklyuchenie-lcd1602-po-i2c-k-arduino