Witam,
Jestem w trakcie przerabiania kursu z EdW
Pracuje na zestawie startowym ZL3AVR [ATmega32 + kwarc 16MHz]
Podczas pisania kursu była biblioteka avrlib 1.4, teraz pracuję na 1.6. Mam problem z kompilacją programu. Powstają następujące błędy:
Zamieszczam kod programu:
Poniżej zamieszczam pdf z opisem lekcji:
http://www.sendspace.com/file/h3hl3m
Szukałem informacji w plikach biblioteki avrlib, ale nie udało się mi usunąć tych błędów. Miał ktoś również kłopot z tą lekcją kursu??
Jestem w trakcie przerabiania kursu z EdW
![[ATmega32][C] Kurs progamowania w C z EdW Lekcja 9 [ATmega32][C] Kurs progamowania w C z EdW Lekcja 9](https://sklep.avt.pl/photo/product_info/c/d/1/1_cd14968b7852.jpg)
Pracuje na zestawie startowym ZL3AVR [ATmega32 + kwarc 16MHz]
Podczas pisania kursu była biblioteka avrlib 1.4, teraz pracuję na 1.6. Mam problem z kompilacją programu. Powstają następujące błędy:
![[ATmega32][C] Kurs progamowania w C z EdW Lekcja 9 [ATmega32][C] Kurs progamowania w C z EdW Lekcja 9](https://obrazki.elektroda.pl/1437402200_1293085912_thumb.jpg)
Zamieszczam kod programu:
/////////////////////////////////////////////////////////////////////////////////////////////
// main.c - testowanie zaawansowanej obsługi alfanumerycznego wyświetlacza LCD
// Program dla płytki testowej AVT3505
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#include <avr/io.h>
#include <inttypes.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "makra.h"
#include "harddef.h"
#include "lcd.h"
#include "local.h"
// Opóźnienie o 10ms x t
void delay_10ms8(uint8_t t)
{
do
{
_delay_ms(10); // dla 8MHz możemy opóźnić o max 32ms
} while(t--!=0);
}
int main(void)
{
// Inicjacja wyprowadzeń
DDR(LCD_CTRLPORT) = (1<<LCD_E | 1<<LCD_RW | 1<<LCD_RS | 1<<LCD_LED);
PORT(LCD_CTRLPORT) = ~(1<<LCD_E | 1<<LCD_LED);
// Test biblioteki wyświetlacza
lcd_Init();
lcd_SetStatus(LCD_STATUS_DISP|LCD_STATUS_CURSOR);
// Wypisanie przywitania
fputs_P(str_Hello, lcd_GetFile());
lcd_Update();
delay_10ms8(200);
// Przewijanie
uint8_t start=0;
for(;;)
{
lcd_Cls();
fputs_P(str_all+start, lcd_GetFile());
lcd_Update();
if(++start >= strlen_P(str_all))
start = 0;
delay_10ms8(100);
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// lcd.c - plik źródłowy do obsługi alfanumerycznego wyświetlacza LCD.
// ! Dynamiczne przydzielanie znaków specjalnych !
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <string.h>
#include <avr/pgmspace.h>
#include "makra.h"
#include "harddef.h"
#include "lcd.h"
#include "local.h"
//__________________________________________________________________________________________
// Definicje stałych
// 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
//__________________________________________________________________________________________
// Deklaracje funkcji które muszą być tutaj zdeklarowane
static int lcd_put(char c, FILE* f);
//__________________________________________________________________________________________
// Zmienne
// Korzystamy z nowej możliwości avrlibc 1.4
static FILE lcd_fLCD_temp = FDEV_SETUP_STREAM(lcd_put, NULL, _FDEV_SETUP_WRITE);
#define lcd_fLCD (&lcd_fLCD_temp)
// Uwaga - wyświetlacz niewykorzystuje kodów 0x80-0x9f. To 32 kody które zostaną wykorzystane dla znaków specjalnych
static char lcd_buffer[LCD_SX*LCD_SY];
// Aktualne pozycja kursora (dotyczy bufora i jest aktualizwana przy odświerzaniu napisu)
static uint8_t lcd_curpos;
// Informacja o tym jakie znaki specjalne zostały zapisane do wyświetlacza
static uint8_t lcd_spec[8];
// Zmienna przechowująca flagi na temat włączenia wyświetlacza (wyświetlacz, kursor, migający kursor)
static uint8_t lcd_status;
//__________________________________________________________________________________________
// Obsługa LCD - funkcje niskiego poziomu
// Impuls ENABLE - przede wszystkim dla zapisu
// Odczyt wymaga trochę bardziej skomplikowanej sekwencji
#define lcd_epulse() \
{PORT(LCD_CTRLPORT) |= 1<<LCD_E; \
_delay_us(0.25); \
PORT(LCD_CTRLPORT) &= ~(1<<LCD_E);}
// Odbiór danej - funkcja wewnętrzna
static inline uint8_t lcd_Get(void)
{
uint8_t dana;
// Ustawienie portu lcd jako wejścia
DDR(LCD_DATAPORT) = 0x00;
// Aktywacja odczytu
PORT(LCD_CTRLPORT) |= 1<<LCD_E;
// \/ Uwaga - sprawdziłem eksperymentalnie,
// \/ że 0.5us to czasami za mało
// \/ przy podłączonym programatorze wyświetlacz
// \/ wciąż gubił dane
_delay_us(1);
// Skopiowanie danych z wyjścia modułu
dana = PIN(LCD_DATAPORT);
// Deaktywacja wyjścia ENABLE
PORT(LCD_CTRLPORT) &= ~(1<<LCD_E);
return dana;
}
uint8_t lcd_GetBF(void)
{
// Wysterowanie wyprowadzeń do odczytu statusu
PORT(LCD_CTRLPORT) |= 1<<LCD_RW;
PORT(LCD_CTRLPORT) &= ~(1<<LCD_RS);
// Odczekanie wymaganego przez sterownik czasu
_delay_us(0.25);
// Odczyt danej
return lcd_Get();
}
// Sprawdza flagę zajętości i czeka na jej wyzerowanie
void lcd_WaitBF(void)
{
// Bit zajętości to bit najstarszy
while(0 != (0x80 & lcd_GetBF())) {};
}
// Wysłanie danej - funkcja wewnętrzna
static void lcd_Send(uint8_t dana)
{
// Ustawienie portu lcd jako wyjścia
DDR(LCD_DATAPORT) = 0xFF;
// Presłanie na port danej
PORT(LCD_DATAPORT) = dana;
// Przesłanie do lcd
lcd_epulse();
}
// Wysłanie danej do pamięci DDRAM lub CGRAM
// Zależnie od ustawionego adresu
void lcd_SendData(uint8_t dana)
{
lcd_WaitBF();
// Wysterowanie wyprowadzeń dla zapisu danej
PORT(LCD_CTRLPORT) &= ~(1<<LCD_RW);
PORT(LCD_CTRLPORT) |= 1<<LCD_RS;
// Odczekanie oraz wysłanie
_delay_us(0.25);
lcd_Send(dana);
}
// Wysłanie instrukcji sterującej
void lcd_SendInstr(uint8_t dana)
{
lcd_WaitBF();
// Wysterowanie wyprowadzeń dla zapisu instrukcji
PORT(LCD_CTRLPORT) &= ~(1<<LCD_RW | 1<<LCD_RS);
// Odczekanie oraz wysłanie
_delay_us(0.25);
lcd_Send(dana);
}
//__________________________________________________________________________________________
// Funkcje obsługujące wejście wyjście strumienia
static int lcd_put(char c, FILE* f)
{
// Zabezpieczenie przed przepełnieniem
if(lcd_curpos >= ELEMS(lcd_buffer))
lcd_curpos = 0;
// Zapis do bufora
lcd_buffer[lcd_curpos++] = c;
return 0;
}
//__________________________________________________________________________________________
// Funkcje interfejsu
// inicjacja LCD (uwaga - nie włączam wyświetlacza ani kursora)
void lcd_Init(void)
{
lcd_Cls();
PORT(LCD_CTRLPORT) &= ~(1<<LCD_RW | 1<<LCD_RS);
_delay_us(0.25);
lcd_Send(LCDC_FUNC | LCDC_FUNC8b);
_delay_ms(4.3);
lcd_Send(LCDC_FUNC | LCDC_FUNC8b);
_delay_us(200);
lcd_Send(LCDC_FUNC | LCDC_FUNC8b);
// Już można sprawdzać BF
#if LCD_SY == 1
lcd_SendInstr(LCDC_FUNC | LCDC_FUNC8b | LCDC_FUNC1L);
#else
lcd_SendInstr(LCDC_FUNC | LCDC_FUNC8b | LCDC_FUNC2L);
#endif
lcd_SendInstr(LCDC_ON);
lcd_SendInstr(LCDC_CLS);
lcd_SendInstr(LCDC_MODE | LCDC_MODER);
lcd_WaitBF();
// Koniec inicjacji. Wyjątkowo czekam na zakończenie. Normalnie BF jest sprawdzana przed wykonaniem indtrukcji
// - daje to większą oszczędność czasu. Podczas inicjacji nie ma to wielkiego znaczenia.
}
// Zerowanie bufora wyświetlacza
void lcd_Cls(void)
{
lcd_curpos = 0;
memset(lcd_buffer, ' ', sizeof(lcd_buffer));
}
// kontrola włączenia wyświetlacza, kursora, migającego kursora
void lcd_SetStatus(uint8_t status)
{
lcd_status = status;
}
// Odswierzenie statusu
inline void lcd_UpdateStatus(void)
{
lcd_SendInstr(LCDC_ON | lcd_status);
}
// Funkcja wewnętrzna podająca początek danej linii
static uint8_t lcd_LineStart(uint8_t line)
{
#if LCD_SY == 1
return LCD_LINE1;
#elif LCD_SY == 2
if(line == 0)
return LCD_LINE1;
else
return LCD_LINE2;
#elif LCD_SY == 4
if(line == 0)
return LCD_LINE1;
else if(linenum == 1)
return LCD_LINE2;
else if(linenum == 2)
return LCD_LINE3;
else
return LCD_LINE4;
#else
#error Unknown display type!
#endif
}
// Ustawienie kursora
inline void lcd_GoToAdr(uint8_t adr)
{
lcd_curpos = adr;
}
// Odswierzenie pozycji kursora
void lcd_UpdateCurPos(void)
{
// Obliczenie adresu w wyświetlaczu
uint8_t adres =
lcd_LineStart(lcd_curpos / LCD_SX) + (lcd_curpos % LCD_SX);
// Wysłanie instrkucji ustawiającej kursor
lcd_SendInstr(LCDC_DDA | adres);
}
// Wewnętrzna pomocnicza funkcja sprawdzająca czy dany znak jest znakiem specjalnym
static uint8_t lcd_IsSpec(char c)
{
// Przydział znaków specjalnych na obszar którego LCD nie wykorzystuje
return (c >= 0x80) && (c <= 0x9f);
}
// Zamiana znaku specjalnego na odpowiedni numer w tablicy symboli
static inline uint8_t lcd_Spec2Index(char c)
{
return c-0x80;
}
// Funkcja sprawdzajaca czy w tablicy jest podany znak
// Zwraca: indeks w tablicy gdzie znajduje sie dany znak
// lub kod znaku alternatywnego (zawsze >= 0x20)
static uint8_t lcd_GetSpec(uint8_t s_index)
{
uint8_t a;
for(a=0; a<ELEMS(lcd_spec); a++)
{
// 0xff oznacza, że nie ma już dalej wpisów
if(lcd_spec[a] == 0xff)
break;
// Jeśli znaleziono...
else if(lcd_spec[a] == s_index)
return a;
}
// Nic nie znaleziono
return pgm_read_byte(&(local_lcdspec[s_index].cAlt));
}
// Makro pomocnicze
#define LCD_SPECNF(spec) (spec > 7)
// Funkcja przydzielająca znaki specjalne
// Zwraca ilość różnych znaków jaką znaleziono. Jeśli > 8 części znaków nie udało się przydzielić
uint8_t lcd_PrepareSpec(void)
{
// Analizuję cały łańcuch danych i zapisuję kolejno znalezione znaki
char* pbuffer = lcd_buffer;
uint8_t n;
uint8_t cnt=0;
char znak;
// Na początku "zerowanie" tablicy znaków specjalnych
memset(lcd_spec, 0xff, sizeof(lcd_spec));
// dodawanie wpisów
for(n=0; n<ELEMS(lcd_buffer); n++)
{
znak = *pbuffer++;
// Jeśli znaleziony znak jest specjalny
if(lcd_IsSpec(znak))
{
// Przeszukanie tablicy
znak = lcd_Spec2Index(znak);
// Jeśli nie znaleziono - dodawanie
if(LCD_SPECNF(lcd_GetSpec(znak)))
{
// dodaj do tablicy tylko jeśli
// nie wystąpiło przepełnienie
if(cnt < ELEMS(lcd_spec))
lcd_spec[cnt] = znak;
// Licznik zwiększany zawsze
// dla statystyki
++cnt;
}
}
}
return cnt;
}
// Funkcja zapisująca definicje znaków do pamięci CGRAM wyświetlacza
void lcd_UpdateCGRAM(void)
{
// Ustawiam adres w module na początek definicji znaków:
lcd_SendInstr(LCDC_CGA);
// Przesyłanie bloków - tylko do czasu aż mam 0xff w tablicy - koniec danych
uint8_t a;
for(a=0; a<ELEMS(lcd_spec); a++)
{
// 0xff oznacza koniec danych
if(lcd_spec[a] == 0xff) break;
// Wskaźnik na początek danych wyglądu znaku
uint8_t* pdata = local_lcdspec[lcd_spec[a]].matrix;
// Wysyłam kolejny indeks
uint8_t bait;
for(bait=0; bait<8; bait++)
{
lcd_SendData(pgm_read_byte(pdata++));
}
}
}
// Funckcja odświerzająca dane w pamięci DDRAM wyświetlacza
// Aby wyświetlanie przebiegło prawidłowo pamięć CGRAM musi być już ustawiona
void lcd_UpdateText(void)
{
uint8_t x, y;
char *pbuffer = lcd_buffer;
// Przetwarzanie każdej linii oddzielnie
for(y=0; y<LCD_SY; y++)
{
lcd_SendInstr(LCDC_DDA | lcd_LineStart(y));
// Wysłanie wszystkich znaków z danej linii
for(x=0; x<LCD_SX; x++)
{
uint8_t znak = *pbuffer++;
if(lcd_IsSpec(znak))
znak = lcd_GetSpec(lcd_Spec2Index(znak));
// Znak gotowy do wysłania
lcd_SendData(znak);
}
}
}
// Odświerzenie wszystkich danych wyświetlacza
void lcd_Update(void)
{
lcd_PrepareSpec();
lcd_UpdateCGRAM();
// Wyłączenie kursora na czas odświerzania
lcd_SendInstr(LCDC_ON | (lcd_status & LCD_STATUS_DISP));
lcd_UpdateText();
lcd_UpdateCurPos();
// Ponowne włączenie kursora (jeśli był włączony)
lcd_UpdateStatus();
}
//__________________________________________________________________________________________
// Funkcja podająca uchwyt do strumienia
inline FILE* lcd_GetFile(void)
{
return lcd_fLCD;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// local.c - wszystkie dane lokalizowalne
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#include <avr/pgmspace.h>
#include "lcd.h" // potrzebuję tego nagłówka ze względu na definicję tablicy znaków specjalnych
// Definicja znaków narodowych
// (Polski ma ich 18)
LCD_LOCAL_PGM local_lcdspec[18] =
{
// Znaczki - poprawiłem pod względem wyglądu znaczki z EdW 1/98, dodałem brakujące
{{0, 0, 14, 1, 15, 17, 15, 2}, 'a'}, //ą - kod 0x80
{{2, 4, 14, 16, 16, 17, 14, 0}, 'c'}, //ć - kod 0x81
{{0, 0, 14, 17, 31, 16, 14, 2}, 'e'}, //ę - kod 0x82
{{12, 4, 6, 4, 12, 4, 14, 0}, 'l'}, //ł - kod 0x83
{{2, 4, 22, 25, 17, 17, 17, 0}, 'n'}, //ń - kod 0x84
{{2, 4, 14, 17, 17, 17, 14, 0}, 'o'}, //ó - kod 0x85
{{2, 4, 14, 16, 14, 1, 30, 0}, 's'}, //ś - kod 0x86
{{2, 4, 31, 2, 4, 8, 31, 0}, 'z'}, //ź - kod 0x87
{{4, 0, 31, 2, 4, 8, 31, 0}, 'z'}, //ż - kod 0x88
{{14, 17, 17, 31, 17, 17, 17, 2}, 'A'}, //Ą - kod 0x89
{{2, 14, 21, 16, 16, 16, 17, 14}, 'C'}, //Ć - kod 0x8a
{{31, 16, 16, 30, 16, 16, 31, 2}, 'E'}, //Ę - kod 0x8b
{{16, 16, 20, 24, 16, 16, 31, 0}, 'L'}, //Ł - kod 0x8c
{{2, 21, 17, 25, 21, 19, 17, 17}, 'N'}, //Ń - kod 0x8d
{{2, 14, 21, 17, 17, 17, 17, 14}, 'O'}, //Ó - kod 0x8e
{{2, 15, 20, 16, 14, 1, 1, 30}, 'S'}, //Ś - kod 0x8f
{{2, 31, 5, 2, 4, 8, 16, 31}, 'Z'}, //Ź - kod 0x90
{{4, 31, 1, 2, 4, 8, 16, 31}, 'Z'}, //Ż - kod 0x91
};
// Napisy
prog_char str_Hello[] = "Cze\x86\x81";
//prog_char str_Hello[] = "fl\x80dra";
//prog_char str_Hello[] = "fl\x80""dra";
prog_char str_all[] = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91";
/////////////////////////////////////////////////////////////////////////////////////////////
// lcd.h - plik nagłówkowy do obsługi alfanumerycznego wyświetlacza LCD.
// ! Dynamiczne przydzielanie znaków specjalnych !
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#ifndef LCD_H_INCLUDED
#define LCD_H_INCLUDED
#include <avr/pgmspace.h>
#include <stdio.h>
// Struktura definiująca wygląd znaku specjalnego
typedef struct LCD_LOCAL
{
uint8_t matrix[8]; // Matryca znaku
char cAlt; // Znak alternatywny
}LCD_LOCAL_PGM PROGMEM;
// Definicje funkcji interfejsu
void lcd_Init(void);
void lcd_Cls(void);
void lcd_SetStatus(uint8_t status);
#define LCD_STATUS_BLINK 0x01
#define LCD_STATUS_CURSOR 0x02
#define LCD_STATUS_DISP 0x04
inline void lcd_UpdateStatus(void);
inline void lcd_GoToAdr(uint8_t adr);
#define lcd_GoTo(x, y) lcd_GoToAdr(y*LCD_SX+x);
void lcd_UpdateCurPos(void);
uint8_t lcd_PrepareSpec(void);
void lcd_UpdateCGRAM(void);
void lcd_UpdateText(void);
void lcd_Update(void);
inline FILE* lcd_GetFile(void);
#endif // LCD_H_INCLUDED
/////////////////////////////////////////////////////////////////////////////////////////////
// local.h - plik nagłówkowy do wszystkich danych które muszą zostać zlokalizowane
// teksty oraz znaki narodowe (specjalne)
// Dołącz ten plik wszędzie tam gdzie chcesz korzystać ze zmiennych zawartych w local.c
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#ifndef LOCAL_H_INCLUDED
#define LOCAL_H_INCLUDED
extern LCD_LOCAL_PGM local_lcdspec[];
extern prog_char str_Hello[];
extern prog_char str_all[];
#endif // LOCAL_H_INCLUDED
/////////////////////////////////////////////////////////////////////////////////////////////
// harddef.h - definicja sprzętu dla programu zaawansowanej obsługi alfanumerycznego wyśw. LCD
//
// Autor: Radosław Koppel Kompilator: WinAVR 20060125
/////////////////////////////////////////////////////////////////////////////////////////////
#ifndef HARDDEF_H_INCLUDED
#define HARDDEF_H_INCLUDED
//__________________________________________________
// Definicje wyświetlacza LCD
// Informacje o typie wyświetlacza
#define LCD_SX 16
#define LCD_SY 2
#define LCD_LINE1 0
#define LCD_LINE2 64
// Podłączenie
#define LCD_DATAPORT B
#define LCD_CTRLPORT D
#define LCD_E 4
#define LCD_RW 3
#define LCD_RS 2
#define LCD_LEDPORT D
#define LCD_LED 5
#endif // HARDDEF_H_INCLUDED
//////////////////////////////////////////////////////////////////////////////////////////////////
// makra.h - makra pomocnicze
//
// Autor: Radosław Koppel Kompilator: WinAVR 20050214
//////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef MAKRA_H_INCLUDED
#define MAKRA_H_INCLUDED
// 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)
// NOPek
#define NOP() {asm volatile("nop"::);}
// Ilość elementów tablicy
#define ELEMS(p) (sizeof(p)/sizeof(p[0]))
#endif //MAKRA_H_INCLUDED
Poniżej zamieszczam pdf z opisem lekcji:
http://www.sendspace.com/file/h3hl3m
Szukałem informacji w plikach biblioteki avrlib, ale nie udało się mi usunąć tych błędów. Miał ktoś również kłopot z tą lekcją kursu??