Непонимание, AlmelStudio 7.0, pgmspace и Attiny10

TheZlobik
Offline
Зарегистрирован: 13.03.2019

Сколько не пытался, но все тщетно

Значит имеется: - МК Attiny10

                         - AtmelStudio 7.0

                         - библиотека avr/pgmspace

Собственно стоит задача: методом чарлиплексинга зажигать 4 светодиода (одновременно или по очереди) используя 2 порта, PB0 и PB1.

Имеем 4 светодиода по 2 встречнопараллельных(1нога идет на массу, другая на плюс, их общий вывод на порт)

Зная что порт может иметь 3 состояния, получаем следующие конфигурации портов:

 PROGMEM const  uint8_t sp_ddr [] =
 {
	 0x01,
	 0x01,
	 0x02,
	 0x02
 };
  
 PROGMEM const  uint8_t sp_port [] =
 {
	 0x00,
	 0x01,
	 0x00,
	 0x02 
 };

В связи с ограниченной оперативной (и не только) памятью контроллера, было решено использовать флеш память для хранение данных, но что-то не срослось, если отдельно вызывать каждое состояние, то все работает как надо(если не обращать на разницу в свечении, эта проблема будет решена через таймер), собственно рабочий код:

while(1) {
		
		i++;
		switch (i)
		{
			case 0:
				DDRB=0x01;
				PORTB=0x00;
				_delay_ms(1);
				break;
			case 1:
				DDRB=0x01;
				PORTB=0x01;
				_delay_ms(1);
				break;
			case 2:
				DDRB=0x02;
				PORTB=0x00;
				_delay_ms(1);
				break;
			case 3:
				DDRB=0x02;
				PORTB=0x02;
				_delay_ms(1);
				break;
		}		   
		}
		i++;
 		if (i==4){i=0;}
	}

А теперь собственно проблема, при использовании pgm_read_byte контроллер наотрез отказывается что-либо делать, пробовал и в основном цикле пихать и по таймеру и вписывать значения вручную, такое чувство что компилятор просто не воспринимает библиотеку pgmspase

ISR (TIM0_COMPA_vect) 
{
  lednum ++;
  if (lednum == 4 ) lednum = 0 ;
  
 // if (( 1 << lednum) & pgm_read_byte (& diceplay [state1])) в зависимости от значения ацп, зажигаем от 1 до 4-х светодиодов
 //  {
    PORTB = pgm_read_byte (& sp_port [lednum]);
    DDRB = pgm_read_byte (& sp_ddr [lednum]);

 //   PORTB = pgm_read_byte (sp_port [lednum]);
 //   DDRB = pgm_read_byte ( sp_ddr [lednum]);

  //  PORTB = pgm_read_byte (&( sp_port [lednum]));
  //  DDRB = pgm_read_byte (& (sp_ddr [lednum]));

 //  }
 //  else
 //  {
 //    DDRB = 0 ;
 //  }
}

Прошу помощи, тыкнуть где я не прав

b707
Offline
Зарегистрирован: 26.05.2017

попробуйте читать из прогмем вот так:

PORTB = pgm_read_byte (sp_port  + lednum);

 

TheZlobik
Offline
Зарегистрирован: 13.03.2019

Увы, та же беда, значения просто не записываются в регистры

 

Green
Offline
Зарегистрирован: 01.10.2015

А схема будет работать? Напряжение питания какое? Потому что если 5 вольт, то 2 из 4-х светодиодов будут гореть (светиться). Когда порт будет в 3-м состоянии будут светить оба светодиода - верхний и нижний.

TheZlobik
Offline
Зарегистрирован: 13.03.2019

Питал и от 5 вольт, сейчас остановился на 2.7-2.5. Работает и так и так. А причем тут напряжение питания? 3 состояние порта (HI-Z) или высокоимпедансное состояние порта, это когда  ключ просто отключает выход и он «повисает в воздухе» — соединяется с остальной схемой через высокое сопротивление (импеданс) закрытого транзистора, так что сопротивление на нем близится к "бесконечности?".  

схема для наглядности: 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

TheZlobik, вам из 8 ми байт данных реально нужно всего по 2 бита с каждого байта, то есть все данные можно ужать в 2 байта, Первоначально записать  в  байт данных для DDRB значение 10 10 01 01  а в байт данных для PORTB 10 00 01 00,  затем сдвигать эти биты по кругу влево на 2 шага. Т.к. необходимолсть в счёте шагов  отпадает, то  if или swith тоже не потребуются.

А можно сдвигать биты сразу в порту, без перекладывания в переменные:

setup(){

PORTB=B10000100;

}

ISR (TIM0_COMPA_vect)

PORTB = (PORTB << 2) | (PORTB >> 6);

}

По аналогии сделать для DDRB.