Nefungující první dva piny pro zobrazení na 7 segmentu

Dobrý den,

v programování mikročipů jsem začátečník a na výšce jsme dostali semestrální práci na sestrojení programu, který bude snímat teplotu na 4 různých senzorech. Prakticky se nejedná o sepsání celého programu, ale o rozchození už vytvořeného programu pro jiný typ Atmegy. Jde o program z polského časopisu o elektronice.

Program už se mi relativně podařilo v rámci možností rozchodit, problém, ale je že při zobrazování teploty nesvítí dva segmenty. Jde o to, že porty PD0 a PD1 jsou absolutně mrtvé. Myslíte, že může být chyba v tom, že porty PD0 a PD1 jsou i porty pro sériovou linku nebo je chyba někde v programu? Předem děkuji za jakoukoli pomoc.

Zde je hlavní kód, program má i podprogramy pro WatchDog, snímání teploty a zápis a čtení z EEPROM, ale zobrazení na 7 segmentu je v tomto hlavním kódy.

[code] #include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include “temp.h”
#include “ee_mem.h”
#include “wdog.h”

#define DISP_PORT PORTD
#define DISP_A 0
#define DISP_B 2
#define DISP_C 6
#define DISP_D 5
#define DISP_E 4
#define DISP_F 1
#define DISP_G 7
#define DISP_DP 3

#define ANODES_PORT PORTB
#define ANODE_1 3
#define ANODE_2 0
#define ANODE_3 2
#define ANODE_4 4
#define ANODE_5 1

#define SWITCH_PIN PINB
#define SWITCH 5

#define TEMP_PORT PORTC
#define TCH_1 5
#define TCH_2 4
#define TCH_3 3
#define TCH_4 2

//—constants-------------------
#define MCK 8000000
#define CLEAR 0
#define STOP 0
#define DISABLE 0
#define ZERO 0
#define OFF 0
#define SET 1
#define ENABLE 1
#define MAX 0xFF

//—mains—
#define MAIN_DELAY 10
#define DISP_REFRESH_FREQ 50 //~500Hz

//—switch states—
#define FREE 0
#define PRESSED 1
#define LONG_PRESSED 2
#define NEW_MODE 3
#define SHORT_PRESS_T 50
#define LONG_PRESS_T 200

#define SLIDE_SPEED 100
#define REFRESH_FREQ 90 //1s
#define NEXT_FREQ 3 //2s

#define EEADDRESS 13

//0…9, 10, -,
#define MINUS_CHAR 11
#define NULL 12
static char digits[13] = {0x88, 0xBB, 0x4A, 0x1A, 0x39, 0x1C, 0x0C, 0xB8, 0x08, 0x18, 0x88, 0x7F, 0xFF};

#define ALL_DOTS 4
#define NO_DOTS 5
static char dots[6] = {0xFE, 0xFD, 0xFB, 0xEF, 0xE8, 0xFF};

static volatile char display[5];

static volatile char sw_pin;
static volatile char sync;
char refresh_counter;
char next_counter;
char tchannel;
char tmode;

//-------------------------
char ViewTemp(char channel);
char ScanButton(void);
void RefresfDisplay(void);
void HardInit(void);

//-------------------------
int main(void)
{
char temp;

HardInit();

display[0] = digits[MINUS_CHAR];
display[1] = digits[MINUS_CHAR];
display[2] = digits[MINUS_CHAR];
display[3] = digits[NULL];
display[4] = dots[ALL_DOTS];

TempInit();

//init and restore mode
tmode = ee_read(EEADDRESS);
if (tmode > 4) tmode = 4; 
tchannel = 0;
temp = NEW_MODE;	

//init temp values
		sync = 0;			
		while (!sync);
		cli();
		TempProcess();
		sei();

//init settings

while(1)
{		
	//----------------------------------
	if (temp == PRESSED)
	{
		tmode++;
		temp = NEW_MODE;
	}

	//----------------------------------
	if (temp == NEW_MODE)
	{
		if (tmode > 4) tmode = 0;
		
		if (tmode == 4)
		{
			refresh_counter = 0;
			next_counter = 0;
			display[4] = dots[ALL_DOTS];						
		}
		else
		{
			tchannel = tmode;
			display[4] = dots[tchannel];
		}
	}

	//----------------------------------
	if (temp == LONG_PRESSED)
	{
		sync = 0;			
		while (!sync);
		cli();
		ee_write(EEADDRESS, tmode);
		sei();
		display[0] &= ~(1<<DISP_DP);		
	}

	//----------------------------------
	temp = ScanButton();

	


	//----------------------------------
	if (refresh_counter < REFRESH_FREQ)
		refresh_counter++;
	else
	{			
		refresh_counter = 0;
		sync = 0;			
		while (!sync);
		cli();
		TempProcess();
		sei();

		//----------------------------------
		if (next_counter < NEXT_FREQ)
			next_counter++;
		else
		{
			next_counter = 0;			
			if (tmode == 4) tchannel++;
			if (tchannel > 3) tchannel = 0; 
			//display[4] = dots[tchannel];
			//ViewTemp(tchannel);
		}
		display[4] = dots[tchannel];
		ViewTemp(tchannel);
	}
	
	//---main delay------------------------------
	WdtReset();
	_delay_ms(MAIN_DELAY);
}

}

//-------------------------
char ViewTemp(char channel)
{
int tval;
int digit;
char blank;
char minus = 0;

//---get val---------------------
tval = TempGet(channel);

//---correction-----------------
if (tval & 0x8000) minus = 1;		
tval = tval & 0x7FF;
if (tval > 1250) 
{
	display[0] = digits[MINUS_CHAR];
	display[1] = digits[MINUS_CHAR];
	display[2] = digits[MINUS_CHAR];
	display[3] = digits[NULL];
	return 2;		//exit - value error
} 

//--convert----------------------
blank = SET;
digit = tval / 1000;
if (digit)
{
	display[3] = digits[digit];
	blank = CLEAR;
}
else
{
	if (minus) display[3] = digits[MINUS_CHAR];
	else	   display[3] = digits[NULL];	
}	
//---------------
tval = tval % 1000;
digit = tval / 100;	
if (digit)
{
	display[2] = digits[digit];
}
else
{
	if (blank) 
		display[2] = digits[NULL];	
	else
		display[2] = digits[digit];			
}

//---------------
tval = tval % 100;
digit = tval / 10;
display[1] = digits[digit];

//---------------
tval = tval % 10;
digit = tval;
display[0] = digits[digit];
return 0;

}

//-------------------------
char ScanButton(void)
{
static char sw_counter;
char sw_state = FREE;

//if pressed
if (sw_pin)	
{
	if (sw_counter < MAX) sw_counter++;
	if (sw_counter == LONG_PRESS_T) sw_state = LONG_PRESSED; 			
}
else
{
	if ((sw_counter) && (sw_counter < SHORT_PRESS_T)) sw_state = PRESSED;
	sw_counter = CLEAR;
}

return sw_state;

}

//-------------------------
void RefresfDisplay(void)
{
static char anode;

if (anode < 6) anode++;
else anode = 0;

switch (anode)
{
	case 0x00:
		ANODES_PORT = 0x1F;
		DISP_PORT = display[0];
		ANODES_PORT = ~(1<<ANODE_4);	
	break;
	case 0x01:
		ANODES_PORT = 0x1F;
		DISP_PORT = display[1];
		DISP_PORT &= ~(1<<DISP_DP);
		ANODES_PORT = ~(1<<ANODE_3);	
	break;
	case 0x02:
		ANODES_PORT = 0x1F;
		DISP_PORT = display[2];
		ANODES_PORT = ~(1<<ANODE_2);	
	break;
	case 0x03:
		ANODES_PORT = 0x1F;
		DISP_PORT = display[3];
		ANODES_PORT = ~(1<<ANODE_1);	
	break;
	case 0x04:
		ANODES_PORT = 0x1F;
		DISP_PORT = display[4];
		ANODES_PORT = ~(1<<ANODE_5);
	break;
	case 0x05:
		//when anode 5 active
		sync = 1;
		if ((PINB & (1<<SWITCH)))
			sw_pin = 1;
		else sw_pin = 0;
	break;			
}

}

//-------------------------
void HardInit(void)
{
ANODES_PORT = (1<<ANODE_1 | 1<<ANODE_2 | 1<<ANODE_3 | 1<<ANODE_4 | 1<<ANODE_5);
DDRB = (1<<ANODE_1 | 1<<ANODE_2 | 1<<ANODE_3 | 1<<ANODE_4 | 1<<ANODE_5);

DISP_PORT = MAX;
DDRD = MAX;

WdtSet(6);

TCCR1A = (1<<WGM10 | 1<<WGM11);
TCCR1B = (1<<WGM12 | 1<<WGM13 | 1<<CS12);
OCR1A = DISP_REFRESH_FREQ;
TIMSK = (1<<TOIE1);

sei();

}

//-----------------------------------
SIGNAL(TIMER1_OVF_vect)
{
RefresfDisplay();
}
[/code]

Takhle zběžně bych řekl, že v programu chybu nevidím. Bylo by dobré, abys napsal něco blíže o tom, jaký jsi použil procesor.

Také by bylo dobré, kdybys při zhasínání displeje (deaktivaci anod) použil
ANODES_PORT = 0xFF; nebo alespoň
ANODES_PORT = (0x1F | (1<<SWITCH));
místo toho
ANODES_PORT = 0x1F;.

Stejně tak v HardInit bys měl mít místo
ANODES_PORT = (1<<ANODE_1 | 1<<ANODE_2 | 1<<ANODE_3 | 1<<ANODE_4 | 1<<ANODE_5);
použít buďto
ANODES_PORT = 0xFF; nebo
ANODES_PORT = ((1<<ANODE_1) | (1<<ANODE_2) | (1<<ANODE_3) | (1<<ANODE_4) | (1<<ANODE_5) | (1<<SWITCH));

VŽDY závorkuj jednotlivé výrazy typu (1<<něco) ! Když už nic, tak kvůli přehlednosti.

Zkus přijít na to, proč bys měl ten SWITCH doplnit …

[size=200]_delay_ms(MAIN_DELAY);
Tímhle zpožďovat hlavní smyčku procesoru je ZVĚRSTVO !!!. Procesor celou dobu maká naplno a drtivou většinu času věnuje pouze tomu delay. Tohle v programu tedy OPRAVDU NE !!!.[/size]

Daj presný typ procesora, na ktorom to skúšaš.

Děkuji za rady, co mám upravit na programu. Jak jsem říkal, ten program je převzatý a mám za úkol ho jen transformovat na jiný typ mikrokontroléru. Takže takové rady se opravdu hodí.

Omlouvám se, že jsem to nenapsal hned do prvního příspěvku, chtěl jsem to tam napsal, ale nějak jsem na to zapomněl. Jedná se mikrokontrolér Atmega 32. Používáme celý kit i se zabudovanými perifériemi - tme.eu/cz/details/evb5.1-atmega32/vyvojove-kity-pro-obvody-microchip/and-tech/evb5-1-v5-atmega32/

No tak iba že by v nejakej časti programu “niekto” inicioval zapnutie UARTu. Úplne najrýchlejšia rada, skús tie dva segmenty napojieť na iný port. Alebo aspoň jeden z nich. Na skúšku.
Ak nechceš rozbíjať program kvôli testu jedného , dvoch pinom, potom
napríklad miesto portu D použi port A. To je v programe úplne najjednoduchšia zmena. A uvidíš

Toto testování jsem zkoušel, pokud ten segment dám na jiný port, tak se rozsvítí a naopak jiný segment na daném portu také nefunguje, takže to musí být portem. Na port A jsem to zkusil přenastavit také, ale to to nefungovalo vůbec, jak říkám, jsem v tomto začátečník a asi je nutné změnit více než jen definici portů.

S AUART mě to napadlo také, protože tyto dva porty jsou pro sériovou linku, zkusím ještě celý program i s podprogrami probádat, jestli to někde není zapnuté. Pokud by to tak ale bylo, je v tom případě zvláštní, že danému autorovi programu to fungovalo. Ten program byl původně pro Atmegu 8, tak nevím, jestli tam to třeba nevadí a na Atmeze32 to vadí.

za

while(1)
{

napis

    UCSRB = 0x00; // vymnes RX a TX z UARTu
    PORTD = 0xFF; // DISP_PORT = MAX; //  je to ten isty efekt
    DDRD = 0xFF;  // DDRD = MAX; //  je to ten isty efekt

tým určite vypneš UART. Ale či ho nejaká následná funkcia nezapne? :slight_smile:

Jak psal Martin, dej na začátek svého kódu UCSRB = 0x00;. Předpokládám, že do procesoru v kitu sypeš program po UARTu pomocí bootloaderu a nekomunikuješ s procesorem přímo pomocí programátoru. Dobře napsaný bootloader při startu programu po sobě uklidí tak, jako by tam vůbec nebyl. Pokud po sobě bootloader neuklidí, pak klidně může zůstat UART aktivovaný a tím pádem zůstanou piny odřízlé od IO registrů procesoru.

Po přidání tohoto příkazu už LED displej ukazuje vše jak má, zítra až budu mít cvičení, tak to vyzkouším s více tepelnými senzory, protože daný senzor ukazuje stále stejnou teplotu a ke všemu nemůžu ani vyzkoušet více senzorů, protože je nemám. Ukazování stále stejné teploty, bych ale spíše přičetl tomu, že daný senzor na kitu už je nefunkční.

Děkuji moc za radu a ochotu Vám oběma :slight_smile: . Pokud bych ještě na něco narazil, tak se ozvu, ale už by to snad mělo být v pohodě :slight_smile:.