"Rozsekání" čísla po desítkách
Moderátor: Moderátoři
"Rozsekání" čísla po desítkách
Řešení s dělením mi vždycky nějak selhalo,
Počítání od 0 do 9 podle pulzů mi funguje dobře, rozšíření je problém.
Jinak používám Atmega8, TIMER2 (Nejsou v něm snad žádné záludnosti narozdíl od TIMER0??)
Napadlo mě i klasitké řešení vytvořit si proměnnou pro jednotky, desítky, stovky....ale vzhledem k tomu, že potřebuju jedním signálem přičítat a druhým odečítat (čísla, ne jedničky), tak to nepřichází v úvahu.
Díky
- forbidden
- Příspěvky: 9442
- Registrován: 14 úno 2005, 00:00
- Bydliště: Brno (JN89GF)
- Kontaktovat uživatele:
Původní číslo ale mám samozřejmě uložený ve zvláštní proměnné, abych s ním kdyžtak mohl dělat běžný operace. Ten rozklad je jen kvůli zobrazování.
termit256 píše:Nevim co presne si predstavujes pod pojmem rozsekat na desitky, ale pokud jde o prevod do BCD, deleni by melo fungovat. Pricitej a odecitej si cisla jak chces, ale to co se ma zobrazit preved na BCD. Vydel cislo k zobrazeni 1000 -dostanes tak tisicovky a ty posli na displej, celociselny zbytek vydel 100 (stovky), pak 10 a nakonec ti zbudou jednotky.
Možná 🤐 dotaz: Ale vždycky to počítá celočíselně? není v tom nějaká zrada? nebo existuje fce pro zaokrouhlení na jednotky?
Kód: Vybrat vše
unsigned int number = 1234;
jed = number % 10 // 4
des = (number / 10) % 10 // 3
sto = (number / 100) % 10 // 2
tis = (number / 1000) % 10 // 1
Ale vždycky to počítá celočíselně? není v tom nějaká zrada? nebo existuje fce pro zaokrouhlení na jednotky?
Dělení celočíselných typů probíhá celočíselně.
int a,b,c;
a=7;
b=2;
c=a/b; // c = 3
Asi by bylo dobré přečíst nějakou knihu o C.
Displej bliká, něco se tam děje....
Budu fakt moc vděčnej za radu
#define F_CPU 4000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>
volatile unsigned int cislice;
volatile unsigned int cislo;
volatile unsigned char T1;
volatile unsigned char T2;
volatile unsigned char T3;
//////////////////////////////////////////////////////////////////////////
// TIMER 0
//////////////////////////////////////////////////////////////////////////
ISR (TIMER0_OVF_vect)
{
TCNT0 = 180; // preruseni po 19,2ms
T1++;
T2++;
//////////////////////////////////////////////////////////////////////////
// FCE PRICITANI PULZU - (PB3)
//////////////////////////////////////////////////////////////////////////
switch (T1)//kazdejch 19,2s scannuje pulz
{
case 1:
if ((!(PINB&0b00001000))==1){ //pokud neprisel pulz
T1=0;
}
break;
case 4:
if ((!(PINB&0b00001000))==0){
cislo=cislo+5;
}
else{
T1=0;
}
break;
case 8:
T1=0;
break;
}
//////////////////////////////////////////////////////////////////////////
// ODECITANI PULZU -(PB2)
//////////////////////////////////////////////////////////////////////////
switch (T2)//kazdejch 19,2s scannuje pulz
{
case 1:
if ((!(PINB&0b00000100))==1){
T2=0;
}
break;
case 2:
if ((!(PINB&0b00000100))==0){ //pokud prisel pulz if ((!(PINB&0b00000100))==0)
cislo--;
}
else { //pokud tady neni pulz, tak neceka do konce, ale jde na zacatek cekani
T2=0;
}
break;
case 3:
T2=0;
break;
}
}
//////////////////////////////////////////////////////////////////////////
// TIMER 2
//////////////////////////////////////////////////////////////////////////
ISR (TIMER2_OVF_vect)
{
TCNT0 = 205; //preruseni po 12,8ms
T3++;
switch (T3)
{
case 1:
PORTC|= (0 << PC2); PORTC|= (1 << PC5);//PC5 -ANODA TISICE
if (cislo>=1000){
cislice=cislo/1000;
cislo=cislo-(cislice*1000);
}
else{
cislice=10; //zobrazi se -
}
break;
case 2:
PORTC|= (0 << PC5);PORTC|= (1 << PC4);//PC4 -ANODA STOVKY
if (cislo>=100){
cislice=cislo/100;
cislo=cislo-(cislice*100);
}
else{
cislice=10; //zobrazi se -
}
break;
case 3:
cislice=cislo/100;
PORTC|= (0 << PC4);PORTC|= (1 << PC3);//PC3 -ANODA DESITKY
if (cislo>=10){
cislice=cislo/10;
cislo=cislo-(cislice*10);
}
else{
cislice=10; //zobrazi se -
}
break;
case 4:
PORTC|= (0 << PC3);PORTC|= (1 << PC2); //PC2 -ANODA JEDNOTKY
cislice=cislo;
T3=0;//vymaze casovaci promennou
break;
}
ukazC(cislice);
}
//////////////////////////////////////////////////////////////////////////
// ZOBRAZOVANI CISEL
//////////////////////////////////////////////////////////////////////////
void ukazC (char cislice)
{
switch (cislice)
{
case 0: PORTD = 0b11000000; break;
case 1: PORTD = 0b11111001; break;
case 2: PORTD = 0b10100100; break;
case 3: PORTD = 0b10110000; break;
case 4: PORTD = 0b10011001; break;
case 5: PORTD = 0b10010010; break;
case 6: PORTD = 0b10000010; break;
case 7: PORTD = 0b11011000; break;
case 8: PORTD = 0b10000000; break;
case 9: PORTD = 0b10010000; break;
default: PORTD = 0b10111111; break; //prostredni vodorovna cara
//0b01111111, //tecka
//0b11111111 //nic
}
}
//////////////////////////////////////////////////////////////////////////
// HLAVNI FUNKCE
//////////////////////////////////////////////////////////////////////////
int main (void)
{
DDRB=0b00110010; //1=vystup, 0=vstup ///F7=>preklad programu
DDRC=0b00111100; //C2-C5 jsou spolecny anody
DDRD=0xff; //sedmisegment-vse vystupy
//PORTB|= (1 << PB1); //zapnuti proudu nafurt
PORTD = 0b11111111;
while(1)
{
TCCR0 |= (1 << CS02) | (1 << CS00); // preddelicka /1024 //TCCR0 = 0b00000101;TIMSK = 0b00000011;
TIMSK|= (1 << TOIE0);// prerušenie pri pretečení TCNT0
//TIMER2
TCCR2 |= (1 << CS22) | (1 << CS21)| (1 << CS20); // preddelicka /1024 //TCCR0 = 0b00000101;TIMSK = 0b00000011;
TIMSK|= (1 << TOIE2);// prerušenie pri pretečení TCNT2
sei(); //povol globálne prerušenia
PORTB=0b00110000;
_delay_ms(40);
PORTB ^= (1 << PB5);
_delay_ms(100);
}
}
Tohle predpokladam, ze je preklep a ma byt TCNT2:
TCNT0 = 205; //preruseni po 12,8ms
Takhle tou operaci OR opravdu puvodne nahozenou anodu neodbudis...
PORTC|= (0 << PC3);PORTC|= (1 << PC2); //PC2 -ANODA JEDNOTKY
PORTC|= (0 << PC3); oprav na PORTC&= ~(1 << PC3);
a vsechno dalsi taky...
Takhle reseny program je zrejme velke sousto....
Ono i ty intervaly by to chtelo resit zpusobem, kdy se o to clovek nemusi starat a nastavovat TCNTx na neco v ISR, protoze se tim zanasi systematicka odchylka....
Kód: Vybrat vše
TCNT0 = 205;
nema byt
Kód: Vybrat vše
TCNT2 = 205;
Takhle na pohled mi to prijde divny....
Ten kod ma, obavam se, zasadni koncepcni vady... no uvidis...
A vkladej sem ten zdrojak jako "code", at to neni tak necitelna hruza...
WLAB píše:jsi si jistej, ze v ISR u TIM2 mistoKód: Vybrat vše
TCNT0 = 205;
nema bytKód: Vybrat vše
TCNT2 = 205;
Takhle na pohled mi to prijde divny....
Ten kod ma, obavam se, zasadni koncepcni vady... no uvidis...
A vkladej sem ten zdrojak jako "code", at to neni tak necitelna hruza...
DÍKY MOC ZA TEN TCNT2 !!
To jsem úplně přehlídl, fakt mi to pomohlo!!
Už mi to funguje,
Pokud se ti chce, tak mi prosím (třeba i v bodech) napiš, co se ti na tom koncepčně nezdá...
Jsem začátečník a rád se přiučím
Díky!
Napr. ten multiplex mas rizeny prerusenim a soucasne s kazdym digitem pocitas, co zobrazit a upravujes pri tom hodnotu promenne "cislo", behem te doby ale "cislo" obsahuje nejaky mezivysledek pro zobrazovani, ovsem TIM0, se zda, ze ti ho muze kdykoliv zmenit - ten mezivysledek.... Proste, kdyz nejakou promennou zpracovavas (a tady "cislo" zpracovavas vlastne po celou dobu multiplexu, vyjma jeho navratu na prvni digit), musis mit zajisteno, ze ti do ni nikdo jiny nesahne (TIM 0 ISR) a opacne nesmis (TIM2 ISR) ji menit nekomu, kdo s ni pracuje (TIM0 ISR)... pomohou tomu pomocne promenne a atomicke predavani hodnot (tj. rekneme "neprerusitelne").
Moc nevim, jak to muze fungovat (ale mohl jsem v tom neco prehlednout), protoze ten zobrazovaci multiplex ti vzdycky znici obsah "cislo"...
Taky nechapu, proc jsou v mainu uvnitr while(1) ty incicializace timeru a to povoleni preruseni....