Sida 1 av 1

Test med MAX232 och PIC16F628A

Postat: 1 april 2008, 15:21:18
av bos
Jag fick mina MAX232-kretsar förra veckan, så jag satte mig ner för att leka runt lite och se vad som gick åstadkomma. Med http://www.piclist.com/techref/microchi ... RTtest.htm som referens (samma kopplingsschema och grund till min kod) kopplade jag upp rubbet på däcket och hackade ihop följande:

--------------8<-------------------

Kod: Markera allt

#include <htc.h>
#include <pic16f62xa.h>

__CONFIG(UNPROTECT & LVPDIS & BORDIS & MCLREN & WDTDIS & PWRTDIS & INTIO);

void send(char letter) {
   TXREG = letter;
   while (!TRMT) {
       // Delay until sent
   }
}

void message(void) {
   char msg[] = "16F628A on the air.";
   char *p = msg;

   while (*p++) {
       send(*p);
   }
}

void main() {
   char tmp = 0;

   // Asynch USART, BRGH = 1, Baud = 9600, Error = 0.16%, SPBRG = 25
   // 8n1
   // LSB first
   TRISA = 0;
   TRISB = 0b00000010;                         // Setup RX/TX-pins
   SPBRG = 0x19;
   TXSTA = 0b00100100;                         // Asynch TX + BRGH
   RCSTA = 0b10010000;                         // Asynch RX + SPEN

   while (--tmp > 0) {
       // Short delay to enable proper startup
   }

   // Flush receive buffer
   tmp = RCREG;
   tmp = RCREG;
   tmp = RCREG;

   message();
   send('Y');
   send('o');
   while (1) {
       if (RCIF) {
           tmp = RCREG;
           tmp += 1;
           send(tmp);
       }
   }
}
--------------8<-------------------

Drog sen igång HyperTerminal, ställde in 9600 baud, 8 bitar och ingen stoppbit, och hoppades sen vid kretsens påslagning få se "16F628A on the air." på skärmen, men så lätt kom jag tydligen inte undan. Ingenting dyker upp på skärmen, men om jag vidrör TX-pinnen på PIC:en så sprutar det upp massa skräptecken på skärmen, så någon sorts kontakt finns iallafall.

Jag har trippelkollat kopplingarna men hittar inga fel. Har även från PIClist's inrådan provat att byta kabel till RX/TX då detta tydligen hjälpte vid ett tillfälle, men här är det resultatslöst.

Förslag på felkälla?



EDIT: Lade till code-tagg.

Postat: 1 april 2008, 16:45:41
av Icecap
TXSTA = 0b001001x0;
Du har 0b00100100 men jag användar 0b00100110 vilket fungerar för mig.

Sedan är jag mycket tveksam till din definition:

Kod: Markera allt

void message(void)
  {
  char msg[] = "16F628A on the air.";
  char *p = msg;
  while(*p++)
    {
    send(*p);
    }
  }

Jag hade ju skrivit:
void message(void)
  {
  const char msg[] = "16F628A on the air.";
  char *p = msg;
  while(*p++) send(*p);
  }

och såhär (finputs bara):
void send(char letter)
  {
  while (!TRMT); // Wait for TX to be free
  TXREG = letter;
  }
Men när du får en massa "brus" när du pillar betyder att portpinnen inte är ställd till utgång och då undrar man: startar den alls?

Postat: 1 april 2008, 19:21:22
av bos
Om jag kör "const char msg[]" så vill inte kompilatorn tugga "char *p = msg", med anledningen "Warning [359] main.c; 15.14 illegal conversion between pointer types". Jag ser heller ingen anledning med att köra en konstant där, förutom att spara ett antal bytes kod. Men nu är ju det här bara ett testprojekt, så kodstorlek är inte så relevant.

Du har i övrigt rätt i att koden inte kördes, för den 628:a som jag använde gick aldrig igenom verifieringssteget på Wispen. Så jag kastade den och körde in en ny, och nu klagas det inget vid programmeringen.

Dock så ser jag fortfarande inget på skärmen, trots finputsningarna du föreslog. Har dubbelkollat seriekabeln, och den är rakt kopplad (GND-GND, RX-RX, TX-TX), dubbelkollat kopplingarna på däcket och allt är som det ska vara. Dubbelkollade för säkerhets skull Hyperterminal, och där har jag 9600 baud, 8 data bits, "None" på parity, 1 stop bits och "None" på Flow control.

Kondingarna (alla på 1uF i enlighet med databladet för MAX232) är förvisso inte nya, de kommer från min "junk box", men min DMM säger 1.1uF på samtliga så de kan jag antagligen utesluta. Skulle iofs kunna byta 232:an, men eftersom den är purfärsk från Maxim så verkar det väldigt osannolikt att den skulle vara kajko.

Nu kommer jag inte på fler saker som kan vara orsaken, iallafall inte saker som jag inte dubbelkollat. Serieporten är t.ex hel, eftersom jag kör Wispen på den.

Postat: 1 april 2008, 19:30:18
av bos
Nu gjorde jag såhär: jag kopplade min hembyggda logikanalysator till seriekabelns RX och TX. När jag i terminalprogrammet skriver lite tecken så blinkar dioden för TX, dvs programmet skickar ut tecken. RX lyser dock inte, vilket innebär att PIC:en inte skickar något (vilket den ska).

Med andra ord är det jag som får skrota tutorialen jag hittade och istället får dyka ner i 628ans datablad en gång till. Oftast så funkar ju cargo culting när det gäller testkod, men inte idag tydligen.

Postat: 1 april 2008, 21:10:09
av Icecap
Förklara gärna för mig HUR du får en variabel till att få ett fast värde vid uppstart utan att deklarera den som en konstant?

Jag använder det mycket och när kompilern gnäller (händer "jämt") är det bara att cast'a den:

Kod: Markera allt

void message(void)
  {
  char msg[] = "16F628A on the air.";
  char *p = (char*)msg;
  while(*p++)
    {
    send(*p);
    }
  }


Postat: 1 april 2008, 21:41:26
av bos
> Förklara gärna för mig HUR du får en variabel till att få ett fast värde vid uppstart utan att deklarera den som en konstant?

Det här blir deluxe-offtopic, men OK: Du får en variabel till ett fast värde vid uppstart genom att tilldela den ett värde, förstås.

Ponera:

Kod: Markera allt

#include <htc.h>

void foo1(void) {
	int i;
	char bar_in_foo1[4];

	i = 0;
}

void foo2(void) {
	int i;
	char bar_in_foo2[4] = "Hej";

	i = 0;
}

void main(void) {
	foo1();
	foo2();
	while (1) {};
}
ger (med Hi-Tech PICC, har ingen annan kompilator till hands som klarar PIC):

Kod: Markera allt

1:                 #include <htc.h>
2:                 
3:                 void foo1(void) {
4:                 	int i;
5:                 	char bar_in_foo1[4];
6:                 
7:                 	i = 0;
   7F1    0183     CLRF 0x3
   7F2    01A0     CLRF 0x20
   7F3    01A1     CLRF 0x21
8:                 }
   7F4    0008     RETURN
9:                 
10:                void foo2(void) {
11:                	int i;
12:                	char bar_in_foo2[4] = "Hej";
   7F5    3048     MOVLW 0x48
   7F6    0183     CLRF 0x3
   7F7    00A2     MOVWF 0x22
   7F8    3065     MOVLW 0x65
   7F9    00A3     MOVWF 0x23
   7FA    306A     MOVLW 0x6a
   7FB    00A4     MOVWF 0x24
   7FC    01A5     CLRF 0x25
13:                
14:                	i = 0;
   7FD    01A0     CLRF 0x20
   7FE    01A1     CLRF 0x21
15:                }
   7FF    0008     RETURN
16:                
17:                void main(void) {
18:                	foo1();
   7EE    27F1     CALL 0x7f1
19:                	foo2();
   7EF    27F5     CALL 0x7f5
20:                	while (1) {};
   7F0    2FF0     GOTO 0x7f0
Kort sagt: const är inte ett nödvändigt verktyg för att initialisera en variabel vid deklarationen, men om variabeln i fråga ska tolkas som konstant så kommer det att hjälpa kompilatorn längre fram. Ju mer kompilatorn / länkaren vet om hur konstruktioner används desto effektivare kan de optimera. Man sparar lagringsutrymme om man inte sätter variabler som är globala och/eller static till 0 explicit. Sätter man dem till 0 hamnar de i binärens datasegment och tar upp plats både på disk/flash/ROM och i RAM (om variablerna är skrivbara (dvs inte const) så måste de ju kopieras till RAM innan binären exekveras, även om kod och konstanta variabler ligger kvar i flash/ROM).

Sätter man inte variablerna explicit kommer de istället hamna i BSS-segmentet som enbart allokeras i RAM och sätts till 0 när binären startar. C-standarden garanterar inte detta, men enligt välinformerad källa så garanteras det av ABI:t på de flesta plattformar som mikrocontrollers sitter på.

Om man vill banta ner kod så är ett annat bra sätt att minska binärstorleken när man räknar bytes att sätta alla funktioner och globala variabler som inte används utanför en given fil till static, och alla variabler som inte modifieras till const.

I min kod ligger strängen lokalt i en funktion, och initialiseras alltså vid funktionsanropet. Ganska mycket overhead, men som redan skrivet så är koden bara en testkod där det primära målet är att få upp text i terminalprogrammet. Nästa steg är att lära mig ytterligare om USART-modulen, och sen - *sist av allt* - mikrooptimera saker och ting.