DIODY- AVR- mikrokontroler

DIODY- AVR- mikrokontroler
M3
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 lat
  • Postów:13
0

Cześć. Jak zaprogramować mikrokontroler ATMEGA 16 w AVR studio, tak aby zaświecić po dwie diody od lewej do prawej, a na końcu wszystkie naraz? Proszę o pomoc, jestem w tym zielony.

atmal
  • Rejestracja:około 8 lat
  • Ostatnio:21 dni
  • Postów:913
1

Od lewej do prawej czyli jak? Od PB0 aż do PA0?

Zakładając, że masz 8 diod, wszystkie na PB

Kopiuj
DDRB = 0xFF; // Wszystkie PBx jako wyjścia
PORTB = 0x03; // 0000 0011 
_delay_ms(500); // Dołącz util/delay.h
for(int i = 0;i < 3; i++)
{
	PORTB <<= 2; // Przesunięcie o 2 miejsca
	_delay_ms(500);
}
PORTB = 0xFF;

DDRB to rejestr w którym ustawiasz jaka nóżka PB jest wejściem a jaka wyjściem.
PORTB natomiast to rejestr w którym ustawiasz stan wyjściowy nóżek PB

<<= 2 przypisuje wynik przesunięcia bitowego o dwa.
Dla przykładu:

Kopiuj
0000 0001 <<= 1
0000 0010

0000 0001 <<= 2
0000 0100

Nie testowałem powyższego kodu na AVR, ale powinien działać


Failure of one test is a tragedy, failure of fifty is a statistic.
edytowany 2x, ostatnio: atmal
M3
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 lat
  • Postów:13
0

Parami po dwie diody na jedną sekundę, tj.: dwie się palą, po sekundzie gasną, i po nich następne pary. Tak od lewej strony do prawej. Na końcu mają zapalić się wszystkie diody. Podpinam je od PB0 do PB8. Każdy kabelek pojedyńczo.

atmal
  • Rejestracja:około 8 lat
  • Ostatnio:21 dni
  • Postów:913
0

No to masz rozwiązanie w moim pierwszym poście, jedyne co to musisz zwiększyć delay do 1000 (ms).


Failure of one test is a tragedy, failure of fifty is a statistic.
edytowany 1x, ostatnio: atmal
lxs
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad 3 lata
  • Postów:45
0

Proponuję zrezygnować z delay'a i zrobić to za pomocą switcha, który będzie wywoływany co jakiś określony czas, tak aby nie blokować uC.

edytowany 1x, ostatnio: lxs
M3
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 lat
  • Postów:13
0
lxs napisał(a):

Proponuję zrezygnować z delay'a i zrobić to za pomocą switcha, który będzie wywoływany co jakiś określony czas, tak aby nie blokować uC.

Podasz przykład?

lxs
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad 3 lata
  • Postów:45
0

Zmienna flag_1s jest ustawiana w przerwaniu od timera co 1000ms.

Kopiuj
volatile uint8_t flag_1s = 0;
uint8_t led_state = 0;

DDRB = 0xFF; // Wszystkie PBx jako wyjścia

while (1)
{
	if (flag_1s)
	{
		switch (led_state)
		{
		case 0:
			PORTB = 0x03; // 0000 0011 
			led_state = 1;
			break;
		case 1:
			PORTB <<= 2;
			led_state = 2;
			break;
		case 2:
			PORTB <<= 2;
			led_state = 3;
			break;
		case 3:
			PORTB <<= 2;
			led_state = 4;
			break;
		case 4:
			PORTB = 0xFF;;
			break;
		}
		flag_1s = 0;
	}
}

edytowany 3x, ostatnio: lxs
atmal
  • Rejestracja:około 8 lat
  • Ostatnio:21 dni
  • Postów:913
0

A to świecenie diodami ma odbyć się tylko raz czy będzie się powtarzać?

I nie ładniej wyglądałoby to:

Kopiuj
while(1)
{
	if(flag) // flag zmienia się na 1 co 1 sekundę
	{
		flag = 0;
		PORTB <<= 2;
		if(PORTB == 0x00)
		{
			PORTB = 0xFF;
		}
	}
}

Failure of one test is a tragedy, failure of fifty is a statistic.
edytowany 2x, ostatnio: atmal
M3
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 lat
  • Postów:13
0
atmal napisał(a):

A to świecenie diodami ma odbyć się tylko raz czy będzie się powtarzać?

I nie ładniej wyglądałoby to:

Kopiuj
while(1)
{
	if(flag) // flag zmienia się na 1 co 1 sekundę
	{
		flag = 0;
		PORTB <<= 2;
		if(PORTB == 0x00)
		{
			PORTB = 0xFF;
		}
	}
}

Ma się powtarzać

atmal
  • Rejestracja:około 8 lat
  • Ostatnio:21 dni
  • Postów:913
0

To używając Timera co 1 który ustawia flag na 1 zrobiłbym tak:

Kopiuj
uint8_t reset;
DDRB = 0xFF;
PORTB = 0x03;
while(1)
{

	if(flag)
	{
		flag = 0;
		if(reset)
		{
			PORTB = 0x03;
			reset = 0;
		}
		else
		{
			PORTB <<= 2;
			if(PORTB == 0x00)
			{
				PORTB = 0xFF;
				reset = 1;
			}
		}	
	}	
}

Failure of one test is a tragedy, failure of fifty is a statistic.
edytowany 1x, ostatnio: atmal
Sparrow-hawk
Zabrakło jednego else ;-) Ciężko będzie zobaczyć stan 0x03.
atmal
Rzeczywiście :P Dzięki
Sparrow-hawk
  • Rejestracja:prawie 13 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Katowice
  • Postów:189
0

Ja jeszcze zaproponuję takie rozwiązanie:

Kopiuj
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define LED_DDR DDRC
#define LED_PORT PORTC

enum {
  NUMBER_OF_EFFECTS = 5,
};

/* LEDS are driven by 0 */
const uint8_t effects[NUMBER_OF_EFFECTS] PROGMEM = {
  0xFC, 0xF3, 0xCF, 0x3F, 0x00,
};

volatile uint8_t currentEffect = 0;

/* Init port for LEDS */
void LED_Init();

/* Init timer to CTC mode with tick on every 1s */
void T1_CTC_Init();

int main(void) {
    LED_Init();
    T1_CTC_Init();

    set_sleep_mode(SLEEP_MODE_IDLE);
    sei();
    while (1) {
      LED_PORT = pgm_read_byte(&(effects[currentEffect]));
      sleep_mode();
    }
}

void LED_Init() {
  LED_DDR = 0xff;
  LED_PORT = 0xff;
}

void T1_CTC_Init() {
  TCCR1A = 0;
  TCCR1B =  _BV(WGM12) | _BV(CS12) | _BV(CS10);
  OCR1A = F_CPU / 1024 - 1;
  TIMSK1 |= _BV(OCIE1A);
}

ISR(TIMER1_COMPA_vect) {
  currentEffect = (currentEffect + 1) % NUMBER_OF_EFFECTS;
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.