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

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

alexlaw

Member
Мне показалось, что еще один микроконтроллер, например в паре с ESP, не будет лишним.
Поэтому решил разобраться с ATTINY2313A-PU.
Вот, что получилось.
Теперь попробую описать мои шаги к этому.
Скетч чтоб не потерялся
Код:
//http://arduinolearning.com/code/program-attiny2313-arduino.php
//https://blog.3d-logic.com/2015/01/21/arduino-and-the-tm1637-4-digit-seven-segment-display/
const int clock1 = 6;
const int data1 = 7;
                 /*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
//uint8_t digits2[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D };
unsigned long t;
uint8_t minutes1;
uint8_t seconds1;
byte dot = 128;//двоеточие на дисплее индикатора
void setup() {
  // put your setup code here, to run once:
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);
t=0;
    //запускаем таймер                                                                                                                       
    setupInterrupt();
}

void loop() {
if ((t % 2)==0){
  dot=128;
} else {dot=0;}
if (t==3600){t=0;}
minutes1 = (byte)((t / 60) % 60);
seconds1 = (byte)(t % 60);
write(clock1,data1,digits1[seconds1 % 10],digits1[seconds1 / 10] | dot,digits1[minutes1 % 10],digits1 [minutes1 / 10]);
delay(5);

}

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 setupInterrupt()
{
/*В состав таймера/счетчика входят следующие регистры ввода/вывода:
16битный счетный регистр TCNT1;
16битный регистр захвата ICR1;
два 16битных регистра сравнения — OCR1A и OCR1B;
три 8битных регистра управления — TCCR1A, TCCR1B и TCCR1C.
Каждый из 16битных регистров физически размещается в двух регист
рах ввода/вывода, названия которых получаются добавлением к названию
регистра  буквы  «H»  (старший  байт)  и  «L»  (младший  байт).  Счетный
регистр таймера/счетчика T1 TCNT1, например, размещается в регистрах
TCNT1H:TCNT1L.*/
 
//Разрешение прерывания осуществляется установкой в 1 бита TOIE1
//TIMSK - регистр маски прерываний
  TIMSK &= ~(1 << TOIE1);// Clear bit
//OCIE1B - Флаг разрешения прерывания по совпадению "В" Т1
//OCIE1A - Флаг разрешения прерывания по совпадению "А" Т1
  TIMSK &= ~((1 << OCIE1A) | (1 << OCIE1B));// Clear bit
//Режим Normal
//Это  наиболее  простой  режим  работы  16битного  таймера/счетчика.
//В данном режиме счетный регистр функционирует как обычный суммирующий счетчик.
  TCCR1A &= ~((1 << WGM11) | (1 << WGM10));
  TCCR1B &= ~((1 << WGM13) | (1 << WGM12));
 
  //Fcpu = 8000000 Гц
  //Период тактового сигнала микроконтроллера Tcpu = 1/Fcpu
  //Период тактового сигнала таймера Т1 равен Tt1 = (1/Fcpu)/k = k/Fcpu
  //256/8000000=0.032 мс
  //Делим требуемый интервал времени (1000 мс) на длительность одного такта таймера
  //1000/0.032=31250
  //2^16 + 1 - 31250 = 34287;
  //Выбор источника тактового сигнала таймера/счетчика T1 clk I/O /256

  //clk I/O
  //TCCR1B |= (1 << CS10);// Set bits
  //TCCR1B &= ~((1 << CS11) | (1 << CS12));// Clear bit

  //clk I/O /8
  //TCCR1B |= (1 << CS11);// Set bits
  //TCCR1B &= ~((1 << CS10) | (1 << CS12));// Clear bit

  //clk I/O /64
  //TCCR1B |= (1 << CS11)  | (1 << CS10); // Set bits
  //TCCR1B &= ~(1 << CS12);           // Clear bit

  //clk I/O /256
  TCCR1B |= (1 << CS12);// Set bits
  TCCR1B &= ~((1 << CS10) | (1 << CS11));// Clear bit

  //clk I/O /1024
  //TCCR1B |= (1 << CS12)  | (1 << CS10); // Set bits
  //TCCR1B &= ~(1 << CS11);           // Clear bit

  /* Save value globally for later reload in ISR */
 TCNT1=34287;
 //Флаг разрешения прерывания по переполнению
 TIMSK |= (1 << TOIE1);// Set bits
 
}
//Install the Interrupt Service Routine (ISR) for Timer1 overflow.
ISR(TIMER1_OVF_vect) {
  TCNT1=34287;
  t++;
}

схема
Схема.png

Исходные данные
  1. ATTINY2313A-PU
  2. WAVGAT ардуино Nano Mini-USB С загрузчика Совместимость Nano 3,0 контроллер CH340 драйвер USB 16 мГц Nano v3.0
  3. TM1637 светодиодный дисплей модуль 7 сегмент 4 биты 0,36
  4. Мини USBISP USBASP (MX-USBISP-V4.00 надпись на плате, процессор - мега88)
  5. Windows 8.1 x64
  6. Arduino IDE 1.8.2
  7. Макетная плата
img1.png
img2.png


Продолжение следует...
 

alexlaw

Member
Переделка китайского USBISP на меге88 в USBASP
Updating firmware on USBASP bought from eBay

Nano ISP
5V ------------ 2
GND ---------10
13 ----------- 7 (SCK)
12 ---------- 9 (MISO)
11 ----------- 1 (MOSI)
10 ----------- 5 (RESET)

Устанавливаем драйвера - USBasp - USB programmer for Atmel AVR controllers - fischl.de
Подключаем USBISP
(у меня определилась как HID устройство, горит красный светодиод) - отключаем

Ставим перемычку UP
Подключаем к макетной плате
img4.png

Cмотрим порт (у меня COM3)
Arduino IDE -Инструменты-Arduino as ISP
Файл-Примеры-ArduinoISP - прошиваем Arduino nano
Командная строка в режиме администратора.
Пробуем прочитать USBISP
Код:
"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe" -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c avrisp -P COM3 -b 19200 -p m88 -U flash:r:c:\original_firmware.bin:r
Если да, то шьем.
У меня пошла эта прошивка -
ATmega88.zip
Бросаем прошивку в C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
Набираем команды
Код:
cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin"
Код:
avrdude.exe -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c avrisp -P COM3 -b 19200 -p m88 -v -u -U hfuse:w:0xdf:m -U lfuse:w:0xff:m
Код:
avrdude.exe -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c avrisp -P COM3 -b 19200 -p m88 -U flash:w:atmega88.hex
У меня получилось - теперь горит синий светодиод и появилось USBasp

Правда если у вас нет USBISP, то он и не нужен, можно шить и через Ардуину, но USBISP удобней

Продолжение следует...
 

Вложения

alexlaw

Member
Добавляем поддержку ATtiny2313 в Ардуино IDE
Program an attiny2313 with an Arduino - Arduino Learning
Файл-Настройки-Дополнительные ссылки для менеджера плат - http://drazzy.com/package_drazzy.com_index.json
Инструменты-Плата-Менеджер плат
img5.png
Устанавливаем ATTinyCore
img6.png
Выбираем Clock 8Mhz
Далее - Записать загрузчик
Все.
Если шить Attiny через USBASP, то программатор в соответствии с ресунком выше.
Если через Arduino , то программатор Arduino as ISP.
И последнее распиновка ATTINY2313A-PU
img7.png
 

alexlaw

Member
Поробовал задействовать оба таймера Timer1 и Timer0
Timer1 - в режиме Normal
Timer0 - в режиме СТС -сброс при совпадении
Код:
//http://arduinolearning.com/code/program-attiny2313-arduino.php
//https://blog.3d-logic.com/2015/01/21/arduino-and-the-tm1637-4-digit-seven-segment-display/
#include <avr/interrupt.h>
const int clock1 = 6;
const int data1 = 7;
                 /*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
//uint8_t digits2[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D };
uint8_t t;
uint8_t minutes1;
uint8_t seconds1;
byte dot = 128;//двоеточие на дисплее индикатора
byte b = 0;
byte a = 31;
void setup() {
  // put your setup code here, to run once:
pinMode(clock1, OUTPUT);
pinMode(data1, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
start(clock1,data1);
writeValue(clock1,data1,0x8c);
stop(clock1,data1);
// clear display
write(clock1,data1,0x00, 0x00, 0x00, 0x00);
t=0;
    //запускаем таймер                                                                                                                        
    setupInterrupt1();
    setupInterrupt0();
}

void loop() {
if ((t % 2)==0){
  dot=128;
} else {dot=0;}
if (t==3600){t=0;}
minutes1 = (byte)((t / 60) % 60);
seconds1 = (byte)(t % 60);
write(clock1,data1,digits1[seconds1 % 10],digits1[seconds1 / 10] | dot,digits1[minutes1 % 10],digits1 [minutes1 / 10]);
delay(5);

}

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 setupInterrupt1()
{
/*В состав таймера/счетчика входят следующие регистры ввода/вывода:
16битный счетный регистр TCNT1;
16битный регистр захвата ICR1;
два 16битных регистра сравнения — OCR1A и OCR1B;
три 8битных регистра управления — TCCR1A, TCCR1B и TCCR1C.
Каждый из 16битных регистров физически размещается в двух регист
рах ввода/вывода, названия которых получаются добавлением к названию
регистра  буквы  «H»  (старший  байт)  и  «L»  (младший  байт).  Счетный
регистр таймера/счетчика T1 TCNT1, например, размещается в регистрах
TCNT1H:TCNT1L.*/
 
//Разрешение прерывания осуществляется установкой в 1 бита TOIE1
//TIMSK - регистр маски прерываний
  TIMSK &= ~(1 << TOIE1);// Clear bit
//OCIE1B - Флаг разрешения прерывания по совпадению "В" Т1
//OCIE1A - Флаг разрешения прерывания по совпадению "А" Т1
  TIMSK &= ~((1 << OCIE1A) | (1 << OCIE1B));// Clear bit
//Режим Normal
//Это  наиболее  простой  режим  работы  16битного  таймера/счетчика.
//В данном режиме счетный регистр функционирует как обычный суммирующий счетчик.
  TCCR1A &= ~((1 << WGM11) | (1 << WGM10));
  TCCR1B &= ~((1 << WGM13) | (1 << WGM12));
 
  //Fcpu = 8000000 Гц
  //Период тактового сигнала микроконтроллера Tcpu = 1/Fcpu
  //Период тактового сигнала таймера Т1 равен Tt1 = (1/Fcpu)/k = k/Fcpu
  //256/8000000=0.032 мс
  //Делим требуемый интервал времени (1000 мс) на длительность одного такта таймера
  //1000/0.032=31250
  //2^16 + 1 - 31250 = 34287;
  //Выбор источника тактового сигнала таймера/счетчика T1 clk I/O /256

  //clk I/O
  //TCCR1B |= (1 << CS10);// Set bits
  //TCCR1B &= ~((1 << CS11) | (1 << CS12));// Clear bit

  //clk I/O /8
  //TCCR1B |= (1 << CS11);// Set bits
  //TCCR1B &= ~((1 << CS10) | (1 << CS12));// Clear bit

  //clk I/O /64
  //TCCR1B |= (1 << CS11)  | (1 << CS10); // Set bits
  //TCCR1B &= ~(1 << CS12);           // Clear bit

  //clk I/O /256
  TCCR1B |= (1 << CS12);// Set bits
  TCCR1B &= ~((1 << CS10) | (1 << CS11));// Clear bit

  //clk I/O /1024
  //TCCR1B |= (1 << CS12)  | (1 << CS10); // Set bits
  //TCCR1B &= ~(1 << CS11);           // Clear bit

  /* Save value globally for later reload in ISR */
TCNT1=34287;
//Флаг разрешения прерывания по переполнению
TIMSK |= (1 << TOIE1);// Set bits
 
}
void setupInterrupt0()
{
TIMSK &= ~(1 << TOIE0);// Clear bit  - запрещаем прерывания по переполнению
TIMSK &= ~((1 << OCIE0A) | (1 << OCIE0B));// Clear bit   - запрещаем прерывания по совпадению
//TCCR0A &= ~((1 << WGM01) | (1 << WGM00));// Clear bit - режим Normal
////режим СТС
TCCR0B &= ~(1 << WGM02);// Clear bit
TCCR0A &= ~(1 << WGM00);// Clear bit
TCCR0A |= (1 << WGM01);// Set bits
////Период тактового сигнала таймера Т0
//1024/8000000=0.128 мс
//длительность до совпадения при OCR0A = 254
//254*0,128=32,51 мс
//1000/32.51=30.76 31*32.51=1007.81 (31 совпадение для 1 сек)

  //clk I/O /1024
  TCCR0B |= (1 << CS02)  | (1 << CS00); // Set bits
  TCCR0B &= ~(1 << CS01);           // Clear bit
OCR0A = 254;
//режим СТС
TIMSK &= ~(1 << OCIE0B);// Clear bit
TIMSK |= (1 << OCIE0A);// Set bits
//Флаг разрешения прерывания по переполнению
// TIMSK |= (1 << TOIE0);// Set bits
}

//Install the Interrupt Service Routine (ISR) for Timer1 overflow.
ISR(TIMER1_OVF_vect) {
  TCNT1=34287;
// b=!b;
// digitalWrite(12,b);
  t++;
}
//Install the Interrupt Service Routine (ISR) .
ISR(TIMER0_COMPA_vect) {
  a--;
  if (a<=0){
   b=!b;
  digitalWrite(12,b);
  a=31; 
  }
}
Светодиод подключенный к PB3(pin12) - мигает раз в секунду и на индикаторе отображается счет времени.
PS:
Сделал режим СТС, тк ISR(TIMER0_OVF_vect) - ошибка компиляции (пока не разобрался)
img8.png
 

alexlaw

Member
Немного ошибся в скетче
Исправить - uint16_t t;//uint16_t | unsigned int, word | от 0 до 65535
 

alexlaw

Member
Небольшой пример кода, для режима Power Down с WatchDog
Раз в 8 сек Тинька дергает 12-ой ногой, остальное время спит
Код:
void setup() {
pinMode(12, OUTPUT);
watch_dog_ext();
}

void loop() {
  digitalWrite(12,1);
  delay(500);
  digitalWrite(12,0);
  sleepNow();
  delay(500);
}

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  сторожевой  таймер  рекомендуется сбрасывать.
*/
WDTCSR |= (1 << WDE)  | (1 << WDCE); // Set bits
//8 сек
WDTCSR |= (1 << WDP0)  | (1 << WDP3); // Set bits
WDTCSR &= ~((1 << WDP1)  | (1 << WDP2));// Clear bit
WDTCSR &= ~(1 << WDCE);// Clear bit
WDTCSR |= (1 << WDE);// Set bits
}
Сколько кушает тока, не замерял
 

alexlaw

Member
WatchDog в режиме прерывания (в предыдущем примере в режиме сброса)
Код:
byte a = 0;
void setup() {
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
watch_dog_ext();
}
void loop() {
  digitalWrite(12,a);
  digitalWrite(13,0);
  sleepNow();
  digitalWrite(12,a);
  delay(500);
}
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
//4 сек
WDTCSR |= (1 << WDP3); // Set bits
WDTCSR &= ~((1 << WDP0)  | (1 << WDP1)  | (1 << WDP2));// 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) { //4 сек
digitalWrite(13,1); 
a=!a;
}
 

alexlaw

Member
Здравствуйте.
Кто нибудь писал на Ассемблере для Attiny2313?
Хочу переписать на Ассемблере управление TM1637 в виде ассемблеровских вставок.
От Arduino IDE отказываться не хочу.
Помигать диодами я смог.
Код:
void setup() {
asm volatile
  (
    /*
     *DDRB - регистр направления данных порта B
     *$17 r23
     *PB3 - pin12,PB4 - pin13
     */
    
    "ldi r23,0b00011000" "\n"
    "out 23,r23" "\n" //pinMode(12, OUTPUT);pinMode(13, OUTPUT);
  );

}

void loop() {
   asm volatile
  (
    /*
     *PORTB - регистр данных порта B
     *$18 r24
     */  
//digitalWrite(12,1);digitalWrite(13,1);
    
"ldi r24,0b00011000" "\n"
"out 24,r24" "\n"
  );
delay(500);
   asm volatile
  (
//digitalWrite(12,0);digitalWrite(13,0);
  
"ldi r24,0b00000000" "\n"
"out 24,r24" "\n"
);
delay(500);
}
 

alexlaw

Member
Вот мигание полностью на ассемблере
Код:
void setup() {
asm volatile
  (
    /*
     *DDRB - регистр направления данных порта B
     *$17 r23
     *PB3 - pin12,PB4 - pin13
     */    
    "ldi r23,0b00011000" "\n"
    "out 23,r23" "\n"
  );
}

void loop() {
   asm volatile
  (
    /*
     *PORTB - регистр данных порта B
     *$18 r24
     */     
"ldi r24,0b00011000" "\n"
"out 24,r24" "\n"    
//; Generated by delay loop calculator
//; at http://www.bretmulvey.com/avrdelay.html
//; Delay 4 000 000 cycles
//; 500ms at 8.0 MHz
    "ldi  r18, 21""\n"
    "ldi  r19, 75""\n"
    "ldi  r20, 191""\n"
"L1: dec  r20""\n"
    "brne L1""\n"
    "dec  r19""\n"
    "brne L1""\n"
    "dec  r18""\n"
    "brne L1""\n"
    "nop""\n"
"ldi r24,0b00000000" "\n"
"out 24,r24" "\n"
    "ldi  r18, 21""\n"
    "ldi  r19, 75""\n"
    "ldi  r20, 191""\n"
"L2: dec  r20""\n"
    "brne L2""\n"
    "dec  r19""\n"
    "brne L2""\n"
    "dec  r18""\n"
    "brne L2""\n"
    "nop""\n"
  ); 
}
 

alexlaw

Member
Еще вариант с дисплеем на max7219.
Код:
int slaveSelect=14;
int din=6;
int clk=15;
byte btNum[10]={126,48,109,121,51,91,95,112,127,123};
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(din, OUTPUT);
  pinMode(clk, OUTPUT);
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
sendCommand (8, 79);
sendCommand (7, 91);
sendCommand (6, 103);
sendCommand (5, 1);
sendCommand (4, 127);
sendCommand (3, 109);
sendCommand (2, 95);
sendCommand (1, 95);
}

void loop() {
delay(5);

}
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);
}
IMG_20190531_233111.jpg
 

alexlaw

Member
Датчик температуры ds18b20.
Код:
//за основу взята библиотека http://mypractic.ru/downloads/arduino/OneWire.zip
//DQ датчика к + через резистор 4.7к
#include "OneWire1.h"
OneWire sensDs (7);
byte bufData[2];  // буфер данных
int slaveSelect=14;
int din=6;
int clk=15;
//датчик к PIN7 - PD5 - PORTD
byte Num[10] ={126,48,109,121,51,91,95,112,127,123};
unsigned char temp;
void setup() {
  pinMode(slaveSelect, OUTPUT);
  pinMode(din, OUTPUT);
  pinMode(clk, OUTPUT);
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
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 loop() {
sensDs.reset();  // сброс шины
sensDs.write(0xCC, 0); // пропуск ROM
sensDs.write(0x44, 0); // инициализация измерения
delay(900);  // пауза 0,9 сек
sensDs.reset();  // сброс шины
sensDs.write(0xCC, 0); // пропуск ROM
sensDs.write(0xBE, 0); // команда чтения памяти датчика
sensDs.read_bytes(bufData, 2);  // чтение памяти датчика, 2 байта
temp = bufData[0]>>4 | bufData[1]<<4;
sendCommand (4, Num[temp/10]);
sendCommand (3, Num[temp % 10]);
delay(5000);
}
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);
}
библиотека
OneWire1.zip
IMG_20190609_011740.png
 

Вложения

alexlaw

Member
Аналоговый компаратор.
comparator.png
Код:
void setup() {
pinMode(12, OUTPUT);
ACSR &= ~(1 << ACIE);// Clear bit - Запрещение прерывания от компаратора
ACSR |= (1 << ACD);// Set bits - Выключение компаратора
// Set bits - отключения  входных  цифровых буферов
DIDR |= (1 << AIN1D)  | (1 << AIN0D );
pinMode(9, INPUT);// AIN0
pinMode(10, INPUT);// AIN1
//изменение состояния выхода компаратора с 0 на 1
ACSR |= (1 << ACIS1)  |  (1 << ACIS0); // Set bits
ACSR &= ~(1 << ACD);// Clear bit - Включение компаратора
}

void loop() {
if (ACSR & (1 << ACO)) //если бит ACO установлен
{
   digitalWrite(12,1);
} else {
  digitalWrite(12,0);
}
delay(1000);
}
Код:
void setup() {
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
ACSR &= ~(1 << ACIE);// Clear bit - Запрещение прерывания от компаратора
ACSR |= (1 << ACD);// Set bits - Выключение компаратора
// Set bits - отключения  входных  цифровых буферов
DIDR |= (1 << AIN1D)  | (1 << AIN0D );
pinMode(9, INPUT);// AIN0
pinMode(10, INPUT);// AIN1
//изменение состояния выхода компаратора с 0 на 1
ACSR |= (1 << ACIS1)  |  (1 << ACIS0); // Set bits
ACSR &= ~(1 << ACD);// Clear bit - Включение компаратора
ACSR |= (1 << ACIE);// Set bits - Разрешение прерывания
}
void loop() {
if (ACSR & (1 << ACO)) //если бит ACO установлен
{
   digitalWrite(12,1);
} else {
  digitalWrite(12,0); 
}
delay(1000);
digitalWrite(13,0);
ACSR |= (1 << ACIE);// Set bits - Разрешение прерывания
}
ISR(ANA_COMP_vect){
    digitalWrite(13,1);
    ACSR &= ~(1 << ACIE);// Clear bit - Запрещение прерывания
}
 

alexlaw

Member
Универсальный синхронный/асинхронный приемо\передатчик - USART
USART.png
Код:
byte b=0;
void setup() {
pinMode(12, OUTPUT);
digitalWrite(12,0);
initUSART();
}

void loop() {
  delay(1000);
}

void initUSART() {
//запретить прнерывания от передатчика
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<<RXEN); // Set bits
UCSRB |= (1<<RXCIE); // Set bits Разрешение прерывания по завершении приема.

}
//прерывания по завершении приема.
//9dddddddddddddddddddd9 - сработает 22 раза
ISR(USART_RX_vect){
  if (UDR==0x39)//цифра 9 - сработает 2 раза
  {
    b=!b;
    digitalWrite(12,b);   
  }  
}
Подключаем ардуино к компу.
Для передачи на Тиньку используем Инструменты-Монитор порта-<<отправить>>
скорость 9600.
 

alexlaw

Member
Код:
char charVar[] ={0x41,0x42,0x43,0x44,'E','F','\n','\r'};
byte b=0;
void setup() {
pinMode(12, OUTPUT);
digitalWrite(12,0);
initUSART();
}
void loop() {
for (int i=0;i < 8;i++) {
  USART_Transmit(charVar[i]);
}
delay(2000);
}

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
//UCSRB |= (1<<TXCIE); // Set bits Разрешение прерывания по завершении передачи.
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */ 
   while ( !( UCSRA & (1<<UDRE))) {   
   };
   UDR = data; 
   b=!b;
   digitalWrite(12,b);    
}
//ISR(USART_TX_vect){
 
//  }
USART1.png
 

alexlaw

Member
Код:
char charVar[64];
byte b=0;
byte a=0;
boolean c = false;
void setup() {
pinMode(12, OUTPUT);
digitalWrite(12,0);
//---------------------
//CodeVisionAVR V2.05.0
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x06;
UBRRH=0x00;
UBRRL=0x33;
//---------------------
UCSRB |= (1<<RXCIE) | (1<<TXCIE); // Set bits Разрешение прерывания по завершении приема и передачи.
}

void loop() {
if (c){
USART_Transmit('*');
for (int i=0;i < a;i++) {
  USART_Transmit(charVar[i]);
  charVar[i]=0;
}
USART_Transmit('*');
USART_Transmit('\n');
USART_Transmit('\r');  
}
a=0;
delay(2000);
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */
   while ( !( UCSRA & (1<<UDRE))) {  
   };
   UDR = data;
   b=!b;
   digitalWrite(12,b);   
}
ISR(USART_RX_vect){
  charVar[a]=UDR;
  c=true;
  a++;
  if(a>64)a=0;
}
ISR(USART_TX_vect){
c=false;
}
Прием и передача обратно.
Принимаются данные и отправляются обратно, в начале и в конце ставится звездочка.
PS В ардуину залит "Blink", если в ардуине есть Serial.begin(9600);
то в Мониторе порта принятые от Тиньки данные не отображаются.
Пока не разобрался
 

alexlaw

Member
Прошу прощения за ошибку в коде
if(a>64)a=0;
Код:
char charVar[64];
byte b=0;
byte a=0;
boolean c = false;
void setup() {
pinMode(12, OUTPUT);
digitalWrite(12,0);
//---------------------
//CodeVisionAVR V2.05.0
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x06;
UBRRH=0x00;
UBRRL=0x33;
//---------------------
UCSRB |= (1<<RXCIE) | (1<<TXCIE); // Set bits Разрешение прерывания по завершении приема и передачи.
}

void loop() {
if (c){
USART_Transmit('*');
//если принято байт больше, чем размер бефера  charVar, то
//данные записанные первыми - перезаписываются, остальные данные есть в буфере,
//но назад не отпр
if (a==0)a=64;
for (int i=0;i < a;i++) {
  USART_Transmit(charVar[i]);
  charVar[i]=0;
}
USART_Transmit('*'); 
USART_Transmit('\n');
USART_Transmit('\r');   
}
a=0;
delay(2000);
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */ 
   while ( !( UCSRA & (1<<UDRE))) {   
   };
   UDR = data; 
   b=!b;
   digitalWrite(12,b);    
}
ISR(USART_RX_vect){
  charVar[a]=UDR;
  c=true;
  a++;
  if(a>63)a=0;
}
ISR(USART_TX_vect){
c=false;
}
USART2.png
 

alexlaw

Member
USART в режиме 1-WIRE.
OneWire.png
Код:
//http://microsin.net/programming/AVR/avr318-dallas-1-wire-master.html
//https://www.maximintegrated.com/en/app-notes/index.mvp/id/214
byte bufData[9];  // буфер данных
byte a=0;
void setup() {
pinMode(12, OUTPUT);
digitalWrite(12,0); 
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
//Разрешение прерывания по завершении приема и передачи.
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x06;
UBRRH=0x00;
UBRRL=0x33;
}

void loop() {
USART_Transmit(0xF0);
delay(2000);
}
void USART_Transmit(unsigned int data)
{
   /* Ждать очистки буфера передатчика */ 
   while ( !( UCSRA & (1<<UDRE))) {   
   };
   UDR = data;     
}
ISR(USART_RX_vect){
  bufData[a]=UDR;
//скорость передачи 9600 бод. Передача 0xF0 от UART формирует правильный импульс сброса.
//Если устройства нет, полученное значение будет равно передаваемому значению.
//Одно подчиненное устройство, работающее с минимальной внутренней синхронизацией, изменит ответ на 0xE0.
//Один ведомый, работающий с максимальной внутренней синхронизацией, изменит ответ на 0x90. 
  if (UDR==0xE0)
  {digitalWrite(12,1);} else {
   digitalWrite(12,0);
  }
  a++;
  if(a>8)a=0;

}
//ISR(USART_TX_vect){
//
//}
У меня DS18b20 ответил - 0xF0.
Можно двигаться дальше ...
IMG_20190622_164703.jpg
 

nikolz

Well-known member
alexlaw,
Полагаю, что схему можно существенно упростить
два транзистора заменить одним диодом.
Подумайте над этим.
 
Сверху Снизу