74HC575 a multiplex na atmega

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

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
Aktuell
Příspěvky: 26
Registrován: 14 črc 2010, 02:00

74HC575 a multiplex na atmega

#1 Příspěvek od Aktuell »

Zdravím, mám takový problém, dělám program pro multiplexování BCD displeje pomocí shift registru 595, program jako takový pro posílání stringu a pouštění potřebných bitů na výstup se zdá že funguje dobře, ale když chci přepínat anody pomocí funkce switch case, tak proběhne nejspíš jen první case a druhý už ne a nevím si s tím vůbec rady, kde může být chyba. Na ukázku sem vybral část kódu a zapojení v ISIS, kde by správně mělo být **56, ale je jen ***6 (adresování zjednodušeno jen na dvě poslední cifry).

Kód: Vybrat vše

int i=3456;

unsigned char znaky [10] = {
    0b00000011,		 //0
    0b10011111,		 //1
    0b00100101,		 //2
    0b00001101,		 //3
    0b10011001,		 //4
    0b01101001,		 //5
    0b01000001,		 //6
    0b00011111,		 //7
    0b00000001,		 //8
    0b00001001   };	 //9


unsigned char anody [4] = {
    0b0001,     //0  - 4.digit
    0b0010,     //1  - 3.digit
    0b0100,     //2  - 2.digit 
    0b1000	};  //3  - 1.digit


ISR(TIMER0_OVF_vect)
{
	
tisice=i/1000;  // 4-cif. cislo rozsekej na cifry
pom=i%1000;
stovky=pom/100;
pom=pom%100;
desitky=pom/10;
jednotky=pom%10;
	
			
	switch (cyklus) {
		
	case 0:
			
		data_k_odeslani= (znaky[jednotky]<<4) | anody[0];   // sluč registry pro katody a anody
			
		while(pocet_odeslanych < 12)      //posilam 12 bitu
	
         {  PORTC=PORTC&0b11111110;     //hodiny do nuly
            if(data_k_odeslani & 0x01) PORTC=PORTC|0b00000010;
                   else PORTC=PORTC&0b11111101;
            PORTC=PORTC|0b00000001; // hodiny do jednicky
            data_k_odeslani>>=1; //posun data o bit doprava
            pocet_odeslanych++;
          }

           PORTC=PORTC|0b00000100;  // pusť data na paralelní výstupy
           asm("nop");
           PORTC=PORTC&0b11111011;  // výstupy uzavři

					
	 cyklus=1;
	 break;


	case 1:
			
		data_k_odeslani= (znaky[desitky]<<4) | anody[1];   // sluč registry pro katody a anody
			
		while(pocet_odeslanych < 12)      //posilam 12 bitu
	
         {  PORTC=PORTC&0b11111110;     //hodiny do nuly
            if(data_k_odeslani & 0x01) PORTC=PORTC|0b00000010;
                   else PORTC=PORTC&0b11111101;
            PORTC=PORTC|0b00000001; // hodiny do jednicky
            data_k_odeslani>>=1; //posun data o bit doprava
            pocet_odeslanych++;
          }

           PORTC=PORTC|0b00000100;  // vpusť data na paralelní výstupy
           asm("nop");
           PORTC=PORTC&0b11111011;  // výstupyuzavři
					
					
	 cyklus=0;
	 break;

       } // konec switch
	
TCNT0=217; 
		
}
Přílohy
simul.jpg
(132.09 KiB) Staženo 116 x

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

#2 Příspěvek od AB1 »

Zkus přemýšlet jak se budou měnit bity v posuvných registrech když pokaždé pošleš 12 bitů.

Buď musíš posílat 16 bitů, nebo před posláním 12-ti bitů registry vynulovat.

A pošli kompletní kód.

Uživatelský avatar
procesor
Příspěvky: 5284
Registrován: 02 říj 2009, 02:00
Bydliště: PO

#3 Příspěvek od procesor »

Žeby rozmýšlal? a vyšlo mu, že 12 stačí.
Posledné 4 bity v registri mu môžu byť ukradnuté.
Kde nuluješ "pocet_odeslanych"

Uživatelský avatar
Aktuell
Příspěvky: 26
Registrován: 14 črc 2010, 02:00

#4 Příspěvek od Aktuell »

Nemá být počet odeslaných < 11 (pokud teda počítáme od nuly)?
No já bych se vsadil, že určitě ne, protože 0,1,2,3,4,5,6,7,8,9,10 určitě dohromady nedá 12...

Nechtěl jsem tu zbytečně spamovat celým kódem, tak jsem vybral podstatnou část a doufal že si zbytek každý domyslí, ale asi ne, tak tady pro pořádek celý kód. Uvnitř smyčky while bych problém neviděl, odeslání stringu se zdá že funguje, nefunguje však její ukončení a skočení na další case. Program sem se snažil nějak okomentovat.

Kód: Vybrat vše

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

unsigned char znaky [10] = {   // definuj pole znaků kombinací katod segmentů
    0b00000011,		 //0
    0b10011111,		 //1
    0b00100101,		 //2
    0b00001101,		 //3
    0b10011001,		 //4
    0b01101001,		 //5
    0b01000001,		 //6
    0b00011111,		 //7
    0b00000001,		 //8
    0b00001001   };   //9


unsigned char anody [4] = {   // definuj pole pro anody jednotlivých sedmisegmentovek
    0b0001,     //0  - 4.digit
    0b0010,     //1  - 3.digit
    0b0100,     //2  - 2.digit 
    0b1000	}; //3  - 1.digit

unsigned short int data_k_odeslani, pom, i=3456;
unsigned char pocet_odeslanych = 0, jednotky, desitky, stovky, tisice, cyklus=0;


void main(void)
{
    PORTC=0;         // vynuluj port
    DDRC=0b11111111; // port C jako výstupní
    TIMSK=0b00000001;     // čítač 0 povoleno přerušení (bit0 TIMER0, bit2 TIMER1, bit6 TIMER2)	
	
 //  Nastavení čítač 0
    TCCR0 = 0b00000100;   //   clk/1024 – 101 ; clk/256 – 100 ; clk/64 – 011 ; for clk/8 – 010 ; no presc. - 001
    TCNT0 = 217;          //   2^8 - 1000000 / 256 / 100 = 217  -> 100 Hz

asm("sei");   // Global enable interrupts
	
			while(1)
			{
				
			}
}

ISR(TIMER0_OVF_vect)       //  přerušení overflow timer
{
	
tisice=i/1000;  // 4-cif. cislo rozsekej na cifry
pom=i%1000;
stovky=pom/100;
pom=pom%100;
desitky=pom/10;
jednotky=pom%10;
	
			
	switch (cyklus) {
		
	case 0:
			
		data_k_odeslani= (znaky[jednotky]<<4) | anody[0];   // sluč registry pro katody a anody
			
		while(pocet_odeslanych < 12)      //posilam 12 bitu
	
         {  PORTC=PORTC&0b11111110;     //hodiny do nuly
            if(data_k_odeslani & 1) PORTC=PORTC|0b00000010;  // pokud vymaskovaný bit v proměné není roven nule, pošli jedničku do sériového výstupu
                   else PORTC=PORTC&0b11111101;   // jinak pošli nulu
            PORTC=PORTC|0b00000001; // hodiny do jednicky, povolení vstupu bitu 1 z předch.podm. na sériový výstup
            data_k_odeslani>>=1; //posuň data o bit doprava
            pocet_odeslanych++;
          }

           PORTC=PORTC|0b00000100;  // pusť data na paralelní výstupy
           asm("nop");
           PORTC=PORTC&0b11111011;  // výstupy uzavři

					
	 cyklus=1;
	 break;


	case 1:
			
		data_k_odeslani= (znaky[desitky]<<4) | anody[1];   
			
		while(pocet_odeslanych < 12)     
	
         {  PORTC=PORTC&0b11111110;     
            if(data_k_odeslani & 1) PORTC=PORTC|0b00000010;
                   else PORTC=PORTC&0b11111101;
            PORTC=PORTC|0b00000001; 
            data_k_odeslani>>=1; 
            pocet_odeslanych++;
          }

           PORTC=PORTC|0b00000100;  
           asm("nop");
           PORTC=PORTC&0b11111011;  
					
					
	 cyklus=0;
	 break;

       } // konec switch
	
TCNT0=217; // znovu nastav čítač
		
}

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

#5 Příspěvek od FHonza »

zkus deklarovat proměnnou cyklus jako volatile char

Uživatelský avatar
Aktuell
Příspěvky: 26
Registrován: 14 črc 2010, 02:00

#6 Příspěvek od Aktuell »

FHonza píše:zkus deklarovat proměnnou cyklus jako volatile char
Bohužel nepomohlo :?

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

#7 Příspěvek od FHonza »

zkus přeložit kód bez optimalizace nebo všechny proměnné, které se používají v obsluze přerušení, deklarovat jako volatile. Obecně by globální proměnné, které se používají v obsluze přerušení, měly být takto deklarovány. Jinak hrozí že se po návratu z obsluhy nezachová jejich hodnota.

Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 02:00
Kontaktovat uživatele:

#8 Příspěvek od piitr »

Přijde mi, že nenuluješ pocet_odeslanych před whilem.

Uživatelský avatar
Aktuell
Příspěvky: 26
Registrován: 14 črc 2010, 02:00

#9 Příspěvek od Aktuell »

piitr píše:Přijde mi, že nenuluješ pocet_odeslanych před whilem.
Přišlo ti to správně. A já se domníval že vynulování v deklaraci bude stačit. Díky za vyřešení
Obrázek

Uživatelský avatar
procesor
Příspěvky: 5284
Registrován: 02 říj 2009, 02:00
Bydliště: PO

#10 Příspěvek od procesor »

procesor píše:Žeby rozmýšlal? a vyšlo mu, že 12 stačí.
Posledné 4 bity v registri mu môžu byť ukradnuté.
Kde nuluješ "pocet_odeslanych"
Stačilo by čítať...

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

#11 Příspěvek od AB1 »

procesor píše:Žeby rozmýšlal? a vyšlo mu, že 12 stačí.
Posledné 4 bity v registri mu môžu byť ukradnuté.
Máš pravdu.
Přemýšlet jsem měl já, než jsem to napsal.

Uživatelský avatar
procesor
Příspěvky: 5284
Registrován: 02 říj 2009, 02:00
Bydliště: PO

#12 Příspěvek od procesor »

Tvoj postup by tiež fungoval/nefungoval, mal by iba pár nadbytočných inštrukcií :) a chýbali potrebné-

Uživatelský avatar
procesor
Příspěvky: 5284
Registrován: 02 říj 2009, 02:00
Bydliště: PO

#13 Příspěvek od procesor »

Dnes je to mega... chýb a bežne mega naviac. Proste nikto netuší

Odpovědět

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