Atmega8 - časem řízené přepínání pinů

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

Atmega8 - časem řízené přepínání pinů

#1 Příspěvek od bastlir40 »

Zdravím. Mohl by mi prosím Vás někdo poradit, jak upravím v tomto programu : http://www.daqq.eu/?p=283 změnu logiky na DDRB piny PB1, PB2 a PB3 tak, aby se po čtyřech hodinách měnil jejich stav z 11111101 na 11111011 a pak 11110111 ? Potřebuji aby tento stav se takto pravidelně měnil.
Předem děkuji za každou pomoc a ochotu.
Zdraví vás Mirek

www.mojeelektro.xf.cz
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#2 Příspěvek od FHonza »

V tom programu (i zapojení) je PORTB jako vstupní. Asi nerozumím dotazu.
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

#3 Příspěvek od bastlir40 »

Já mám program upravený tak, že PORTB = 0b11110001; a DDRB potřebuji měnit hodnoty na PIN1 až PIN3 na 011, 101 a 110 po 4 hodinách. Spínám s nimi tranzistory PNP
Zdraví vás Mirek

www.mojeelektro.xf.cz
Uživatelský avatar
nekmil
Příspěvky: 787
Registrován: 06 bře 2005, 00:00
Bydliště: Havířov

#4 Příspěvek od nekmil »

DDRB (Data_Direction_Register_B) slouží k nastavování směru portu nikoliv k posílání nějakých hodnot na piny.
V "hrůzostrašném" jazyku "C" Ti neporadím, jsou tu jiní. :D

DDRB=b00000000 - všechny piny portu B nastaveny jako vstupy
DDRB=b11111111 - všechny piny portu B nastaveny jako výstupy

podle schématu máš na PB3 tlačítko tak tam "nemůžeš" nic posílat
Naposledy upravil(a) nekmil dne 15 dub 2014, 18:59, celkem upraveno 1 x.
Uživatelský avatar
CAMaFo
Příspěvky: 51
Registrován: 07 led 2013, 00:00

#5 Příspěvek od CAMaFo »

Mirku,řešení bude několik.První co mne napadá je,že bych si zvolil globállní proměnnou typu byte,kterou bych při změně hodin inkrementoval (od 0 do 2).Následně bych podle tý proměnný natavoval to co je třeba.Až by byla proměnná 2 (0,1,2) a mělo dojít k inkrementaci,tak bych ji vynuloval a tak pořád dokola.
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

#6 Příspěvek od bastlir40 »

Zde je celé schéma s programem:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <stdio.h>

#define _s_A 0
#define _s_B 1
#define _s_C 2
#define _s_D 3
#define _s_E 4
#define _s_F 5
#define _s_G 6
#define _s_dot 7

const unsigned char segs[] =
{
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //0
_BV(_s_B) | _BV(_s_C), //1
_BV(_s_A) | _BV(_s_B) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //2
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_G), //3
_BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G), //4
_BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G), //5
_BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //6
_BV(_s_A) | _BV(_s_B) | _BV(_s_C), //7
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G),//8
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G),//9

_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //A
_BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //B
_BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //C
_BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //D
_BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //E
_BV(_s_A) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G) //F
};

#define _ms(n) (17*n)

void wait(unsigned int a) //basic wait
{
volatile unsigned int b,c;
for(b=0;b!= a; b++)for(c=0;c!= 50;c++);
return;
}

volatile unsigned char prescale=0;
volatile unsigned char sec=0;
volatile unsigned char min_1=0;
volatile unsigned char min_10=0;
volatile unsigned char hour_1=0;
volatile unsigned char hour_10=0;
volatile unsigned char show_t=0;

ISR(TIMER1_OVF_vect)
{
if(++prescale == 255){prescale = 0;sec++;};
if(sec>59){min_1++;sec=0;};
if(min_1>9){min_1=0;min_10++;};
if(min_10>5){min_10=0;hour_1++;};
if(hour_1>9){hour_1=0;hour_10++;};
if(hour_10>1 && hour_1>3){hour_1=0;hour_10=0;};

if(++show_t==4) show_t=0;
switch(show_t)
{
case 0: //show minutes
PORTC = 0xFB;
PORTD = (segs[min_1]);
break;
case 1: //show 10 minutes
PORTC = 0xF7;
PORTD = (segs[min_10]);
break;
case 2: //show hours
PORTC = 0xEF;
PORTD = (segs[hour_1]) |_BV(_s_dot);
break;
case 3: //show 10hours
PORTC = 0xDF;
PORTD = (segs[hour_10]);
break;
default:
show_t = 0;
break;
}
return;
}

#define B1() (bit_is_clear(PINB,4))
#define B2() (bit_is_clear(PINB,5))
#define B_WAIT 300

#define nop() asm volatile ("nop;")

int main(void)
{

TIMSK = 0x04;
TCCR1B = 0x01;

PORTD = 0xff;
DDRD = 0xff;
PORTC = 0x00;
DDRC = 0xff;
PORTB = 0xf1;
DDRB = 0xfd;


sei();
while(1)
{
if(B1())
{
wait(_ms(B_WAIT));
min_1++;
sec=0;
}
if(B2())
{
wait(_ms(B_WAIT));
hour_1++;
sec=0;
}
}
}
Přílohy
schema.png
(25.44 KiB) Staženo 135 x
Zdraví vás Mirek

www.mojeelektro.xf.cz
Uživatelský avatar
nekmil
Příspěvky: 787
Registrován: 06 bře 2005, 00:00
Bydliště: Havířov

#7 Příspěvek od nekmil »

DDRB = 0xfd - špatně

DDRB = 0x0E - b00001110
PB1, PB2, PB3 nastaveno jako výstupy, zbytek jako vstupy.

No a pak už můžeš posílat nějaká data na PB1, PB2, PB3.

To schéma jsi měl ukázat hned. :)
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

#8 Příspěvek od bastlir40 »

NEKMIL: 0xfd je dobře. Asi si to pleteš s PIC. Tam je to opačně. Když to nastavím jak píšeš, nefunguje to.
Zdraví vás Mirek

www.mojeelektro.xf.cz
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#9 Příspěvek od FHonza »

Já mám program upravený tak, že PORTB = 0b11110001; a DDRB potřebuji měnit hodnoty na PIN1 až PIN3 na 011, 101 a 110 po 4 hodinách.


Máš ty registry prohozené. DDRx řídí směr, PORTx pak co je na výstupu. Je-li v registru DDRx bit nastaven, je pak příslušný pin portu nastaven jako výstupní. V tvém případě to je 0b00001110, tj 0x0e. Registr PORTx v případě že je příslušný pin nastaven jako výstupní, řídí hodnotu na výstupu. V případě že je nastaven jako vstupní, pak řídí zda je na příslušný pin připojen pull-up.

Rozšíření programu při prvním "nástřelu":

Kód: Vybrat vše

...
volatile unsigned char hour_4=0;
...

if(min_10>5)
{
  min_10=0;hour_1++;
  hour_4++;
  switch(hour_4 & 0b1100)
  {
    case 0b0100:
      PORTB = 0b11111011; 
      break;
    case 0b1000:
      PORTB = 0b11110111;
      break;
    case 0b1100:
      PORTB = 0b11111101;
      hour_4 = 0;
      break;
  }
};

...

// a na zacatku pri inicilaizaci
PORTB = 0b11111101;


Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#10 Příspěvek od AB1 »

Ovládání výstupu pomocí registru DDRB se používá u sběrnic, např i2c.
Je to obdoba výstupu s otevřeným kolektorem.
Tady to nemá smysl. Lépe je použít normálně PORTB.

Vyložená chyba je, že piny na kterých jsou tlačítka jsou nastavené jako výstupy (DDRB 4,5 = 1).

Zkus dát do main() toto

Kód: Vybrat vše

unsigned char hour=0, hour_old=0, hour_count=0;

   hour = 10 * hour_10 + hour_1;

   if(((hour % 4) == 0) && (hour != hour_old)) // změna hodin na hodnotu dělitelnou 4
   {
      hour_count++;
      if(hour_count >= 3) {hour_count = 0;}
      hour_old = hour;

      if(hour_count == 0) DDRB = 0b11001011; //PB1=0 PB2=1 PB3=0
      if(hour_count == 1) DDRB = 0b11000111; 
      if(hour_count == 2) DDRB = 0b11001111;
   }


Edit:
Doplněno "0b" u binárních čísel.
Naposledy upravil(a) AB1 dne 16 dub 2014, 12:54, celkem upraveno 1 x.
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#11 Příspěvek od FHonza »

if(hour_count == 0) DDRB = 11001011; //PB1=0 PB2=1 PB3=0
if(hour_count == 1) DDRB = 11000111;
if(hour_count == 2) DDRB = 11001111;


Místo DDRB má být PORTB ne ?
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

#12 Příspěvek od bastlir40 »

Pánové děkuju za pomoc ale pokaždé to na mně vychrlí hromadu chyb a už opravdu nevím jak dál. :cry:
Zdraví vás Mirek

www.mojeelektro.xf.cz
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#13 Příspěvek od AB1 »

FHonza:
Funguje to tak, že např když DDRB1=1 pak na PB1 je 0.
Když DDRB1=0, pak PB1 je odpojený.
Asi spoléhá na to, že tranzistor s bází v luftě bude zavřený.

Ptal se jak měnit DDRB každé 4 hodiny.
Předpokládám, že si to předělá sám na normální zápis do PORTB.
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#14 Příspěvek od FHonza »

AB1:
U případu DDRx = 0 pak záleží jestli je připojen pull-up. Po resetu bude pin ve stavu vysoké impedance. Ale pak je v programu někde PORTB = 0xf1, takže některé budou, některé ne. Ale určitě se shodnem že takhle se výstupy neovládají :) (...kromě I²C)


bastlir40:
jaké myslíš chyby ? V překladu ? Čím program překládáš ?
Uživatelský avatar
bastlir40
Příspěvky: 463
Registrován: 27 srp 2010, 00:00
Bydliště: Příbram

#15 Příspěvek od bastlir40 »

Ano, v překladu. Nemyslel jsem tím že je děláte vy ostatní. Používám AVR Studio 6.
Zdraví vás Mirek

www.mojeelektro.xf.cz
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“