$regfile = "attiny2313.dat"
$crystal = 11000000
Config Portb = &B11111111 : Portb = &B11111111
Config Portd = &B11111111 : Portd = &B11111111
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.1 , Rs = Portb.2
Config Lcd = 16 * 2
Cls
Cursor Off Noblink
Lcd " HELLO WORLD!!!"
Lowerline
Lcd " by GIVER 2008"
Do
Loop
End
Kod się kompiluje bez problemu, programowanie również przebiega bez problemu, efekt w postaci napisu na wyświetlaczu.
//////////////////////////////////////////////////////////////////////////////////////////////////
// LCD_simple.c - plik pokazujący prostą obsługę wyświetlacza alfanumerycznego LCD
//
// Autor: Radosław Koppel Kompilator: WinAVR 20050214
//////////////////////////////////////////////////////////////////////////////////////////////////
// Komentarz dodatkowy:
// Pierwsza wersja. Założenie, że wyprowadzenia portu podpięto "po koleji"
// Brak wygodnych komend, wszystko realizowane na dość niskim poziomie.
//////////////////////////////////////////////////////////////////////////////////////////////////
#include <avr\io.h>
#include <inttypes.h>
// Makra upraszczające dostęp do portów
// *** Port
#define PORT(x) XPORT(x)
#define XPORT(x) (PORT##x)
// *** Pin
#define PIN(x) XPIN(x)
#define XPIN(x) (PIN##x)
// *** DDR
#define DDR(x) XDDR(x)
#define XDDR(x) (DDR##x)
// Definicje wyprowadzeń
#define LCD_RS 2
#define LCD_RSPORT B
#define LCD_E 1
#define LCD_EPORT B
// Port danych: zakładam, że wyprowadzenia są połączone kolejno.
// Definiowane jest jedynie przesunięcie oznaczające na którym wyprowadzeniu jest D4
#define LCD_DPORT B
#define LCD_D4 4 // D5, D6, D7 - połączone kolejno
// Komendy sterujące wyświetlaczem
#define LCDC_CLS 0x01
#define LCDC_HOME 0x02
#define LCDC_MODE 0x04
#define LCDC_MODER 0x02
#define LCDC_MODEL 0
#define LCDC_MODEMOVE 0x01
#define LCDC_ON 0x08
#define LCDC_ONDISPLAY 0x04
#define LCDC_ONCURSOR 0x02
#define LCDC_ONBLINK 0x01
#define LCDC_SHIFT 0x10
#define LCDC_SHIFTDISP 0x08
#define LCDC_SHIFTR 0x04
#define LCDC_SHIFTL 0
#define LCDC_FUNC 0x20
#define LCDC_FUNC8b 0x10
#define LCDC_FUNC4b 0
#define LCDC_FUNC2L 0x08
#define LCDC_FUNC1L 0
#define LCDC_FUNC5x10 0x4
#define LCDC_FUNC5x7 0
#define LCDC_CGA 0x40
#define LCDC_DDA 0x80
//--------------------------------------------------
// Generowanie opóźnień
#define delay250ns() {asm volatile("nop"::);}
#define delayus8(t)\
{asm volatile( \
"delayus8_loop%=: \n\t"\
"nop \n\t"\
"dec %[ticks] \n\t"\
"brne delayus8_loop%= \n\t"\
: :[ticks]"r"(t) );}
// DEC - 1 cykl, BRNE 2 cykle, + 1xnop. Zegar 4MHz
void delay100us8(uint8_t t)
{
while(t>0)
{
delayus8(100);
--t;
}
}
// Koniec opóźnień
//--------------------------------------------------
//--------------------------------------------------
// Obsługa wyświetlacza
// Funkcje niskiego poziomu
#define LCD_EPULSE() \
{PORT(LCD_EPORT) |= 1<<LCD_E; \
delay250ns(); \
PORT(LCD_EPORT) &= ~(1<<LCD_E);}
void LCDsendHalf(uint8_t data)
{
data = (data & 0x0F) << LCD_D4;
//data |= 0xF0;
//data &= 0x0F;
//data <<= LCD_D4;
PORT(LCD_DPORT) =
(PORT(LCD_DPORT) & ~(0x0F<<LCD_D4)) | data;
//PORT(LCD_DPORT) &= ~(0x0F<<LCD_D4);
//PORT(LCD_DPORT) |= data;
LCD_EPULSE();
}
void LCDsend(uint8_t data)
{
// Starsza część
LCDsendHalf(data>>4);
// Młodsza część
LCDsendHalf(data);
delayus8(120);
}
// Funkcje interfejsu
void LCDcommand(uint8_t command)
{
PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
LCDsend(command);
}
void LCDdata(uint8_t data)
{
PORT(LCD_RSPORT) |= 1<<LCD_RS;
LCDsend(data);
}
void LCDcls(void)
{
LCDcommand(LCDC_CLS);
delay100us8(48);
}
void LCDhome(void)
{
LCDcommand(LCDC_HOME);
delay100us8(48);
}
void LCDinit(void)
{
delay100us8(150);
PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
delay100us8(41);
LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
delay100us8(2);
LCDsendHalf(LCDC_FUNC|LCDC_FUNC4b);
delay100us8(2);
// Teraz jest już 4b. Koniec korzystania z sendHalf
LCDcommand(LCDC_FUNC|LCDC_FUNC4b|LCDC_FUNC2L|LCDC_FUNC5x7);
LCDcommand(LCDC_ON);
LCDcls();
LCDcommand(LCDC_MODE|LCDC_MODER);
LCDcommand(LCDC_ON|LCDC_ONDISPLAY|LCDC_ONCURSOR);
}
// Koniec obsługi wyświetlacza
//--------------------------------------------------
// START
int main(void)
{
//----------------------------------------------
// Inicjacja - uwaga: uproszczona, może wymagać
// zmian przy zmianie przyporządkowania portów
DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS |
0x0F<<LCD_D4;
LCDinit();
// Koniec inicjacji
//----------------------------------------------
// \/ Bez tego, czasami zerowanie z poziomu programatora
// \/ powoduje śmieci na wyświetlaczu.
LCDcls();
LCDdata('H');
LCDdata('E');
LCDdata('L');
LCDdata('L');
LCDdata('O');
LCDdata(' ');
LCDdata(':');
LCDdata('-');
LCDdata(')');
return 0;
}
Kod się kompiluje, programator procesor zaprogramował, a na wyświetlaczu nic ...
Podałem pierwszy kod w bascomie, po to, aby pokazać, że mimo takiego samego przyporządkowania wyprowadzeń, kod napisany w bascomie działa a w C już nie.
Korzystam z kompilatora AVR-GCC 20080610, na innych przykładach kodu, działa bez problemu, więc to nie wina środowiska.
Połączenie jest również prawidłowe, skoro pierwszy program działa.
E-B1
RS-B2
D4-B4
D5-B5
D6-B6
D7-B7
