Mám stupidní program. Nastavený časovač, pomocí jehož přerušení neguju stav LED (blikám s ní). Negace stavu LED je podmíněná podmínkou, dejme tomu “stav==163”.
Pak mám dvě procedurky, jedna udělá stav=163 (zapne blikání) a druhá udělá stav=79 (vypne blikání). To dementní AVR studio to není schopné přeložit bez chyby.
Zde máte zdrojový kód kompletní. Zatím ten program nedělá nic jiného, než že při příchodu “z” po UARTu zařízení zapne, případně “v” vypne. Přičemž stav indikuje LED, která bliká, nebo svítí trvale, v případě zapnutí. Ten kód je prostě nefunkční.
// pouzite hlavickove soubory, makra
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 11059200U //frekvence Xtalu procesoru 11,0592MHz
#include <util/delay.h>
//definice BaudRate pro UART
#define UBRRH_2400 1
#define UBRRL_2400 31
char tcr_div1; //sw delicka citace tccr2
char stav; //stav zarizeni: 0:"vypnute", 1:"zapnute"
void Init_Portu(void) //inicializace portu
{
PORTA = 0b00000000; //vstupy ADC
DDRA = 0b00000000;
PORTB = 0b00000001; //PB0 - zapinani napajeni cidel log. 0
DDRB = 0b00000001;
PORTC = 0b00001111; //PC3:0 - jumpery, PC6:5 stavova LED
DDRC = 0b01100000;
PORTD = 0b00000000; //UART vystupy PD1:0
DDRD = 0b00000011;
}
void Init_Periferii(void) //Inicializuje periferie
{
//Init RS232
//Rx & Tx enable, 8 bit, parity none
UCSRA = 0;
UCSRB = (1<<RXEN)|(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
UBRRH = UBRRH_2400;
UBRRL = UBRRL_2400;
//Init ADC
//ADC enable, external reference, :128
ADMUX = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
//TCCR2
//CTC mode, :1024, CTC on 107, CTC INT enable
TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
OCR2 = 107;
TIMSK = (1<<OCIE2);
tcr_div1 = 0;
}
// parametr channel urcuje vstup ADC (0-7)
//vraci navzorkovanou hodnotu (0-1023)
int ADC_Convert(char channel)
{
ADMUX = (ADMUX & 0xF0)|(channel & 0x0F);
ADCSRA |= (1<<ADSC);
while (ADCSRA & (1<<ADSC));
return ADC;
}
void Ser_SendByte(char b) //odesle byte UARTem
{
while (!(UCSRA & (1<<UDRE))); //pockame na prazdny UDR buffer
UDR = b;
while (!(UCSRA & (1<<TXC))); //pockame na odeslani
UCSRA |= (1<<TXC); //vynulujeme TXC flag
}
char Ser_ReceiveByte(void) //precte data z UARTu
{
return UDR;
}
char Ser_WaitingData(void) //vrati 1 pokud cekaji data k precteni
{ //z UARTu, jinak 0
if (UCSRA & (1<<RXC))
{
return 1;
} else {
return 0;
}
}
void LED_Green_On(void) //rozsviti zelenou LED
{
PORTC |= 0b00100000;
}
void LED_Green_Off(void) //zhasne zelenou LED
{
PORTC &=~0b00100000;
}
void LED_Yellow_On(void) //rozsviti zlutou LED
{
PORTC |= 0b01000000;
}
void LED_Yellow_Off(void) //zhasne zlutou LED
{
PORTC &=~0b01000000;
}
void Device_On(void)
{
stav = 67;
LED_Green_On(); //v zapnutem stavu LED musi svitit trvale
PORTB &=~0x01; //zapne napajeni cidlum
}
void Device_Off(void)
{
stav = 163;
LED_Green_Off();
PORTB |= 0x01; //vypne napajeni cidel
}
// ******************************** ISR ******************************
ISR(TIMER2_COMP_vect)
{
tcr_div1++;
if (tcr_div1 == 100)
{
tcr_div1 = 0;
if (stav == 163) LED_Green_On(); //Tady fakt už nevim co s tim
}
if ((tcr_div1 == 5)&&(stav == 163)) //nemluvě o tomhle. Prostě to bliká furt, ať je tam číslo jaké chce.
{
LED_Green_Off();
}
}
// ******************************** MAIN *****************************
char rxd;
int main (void)
{
Init_Portu();
Init_Periferii();
sei();
Device_On();
while (1)
{
while (!Ser_WaitingData());
rxd = Ser_ReceiveByte();
switch (rxd)
{
case 'z':
{
Device_On();
break;
}
case 'v':
{
Device_Off();
break;
}
}
}
while (1) ;
}
Poslední dobou mám sto chutí vrátit se k assembleru. I když tam to neni omoc lepší, protože už jednou se mi stalo, že prostě konkrétní instrukce za sebou je překladač přeložil chybně. Musel jsem mezi to dát NOP aby to začlo fungovat. DAl jsem si tu práci, a ten blok instrukcí našel:
[code]ldi R16, 0b00001110 ;nastavime timer2: Tosc/256, CTC mode - tedy 15625Hz
out TCCR2, R16
ldi R16, 125 ;porovnavame s hodnotou 125 => preruseni vznika 125/s
out OCR2, R16
ldi R16, 0b10000000 ;povolime preruseni od compare match timer 2
out TIMSK, R16
sei ;CHYBNE??
nop
clr R16
sts TL_Start, R16
sts TL_Stop, R16
sts TL_Plus, R16
sts TL_Minus, R16
sts TL_Set, R16
[/code]
Bez toho NOP (ale nepamatuju si to jistě) jsem tu instrkci SEI nenašel snad vůbec v té přeložené binárce.
Přejít zpět na ASM podporuje mě i ještě to, že v C se nedá pořádně pracovat se stringy, musíte si zakydat SRAM, jinak to prostě nejde.
Hledáním jedné chyby v C jsem dnes strávil víc než 3 hodiny. V ASM bych buď tu chybu vůbec neudělal, a nebo jí našel za pár minut. Cčko bohužel příliš pro mě není. Nemám se kde ho naučit, a nikdo v něm pořádně neumí, aby mi poradil (teda nikdo koho znám)