Uživatel:Kvardluk

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Semestrální práce : Třída funkcí pro ovládání grafického LCD displeje

[editovat] Zadání

Můžete vymyslet funkce pro kreslení čar, oblouků a následně pěkných okének s textem, výpisy znaků různých velikostí fontů, řezů, s diakritikou,

Vypracoval : Lukáš Kvarda, Pavel Hnyk


[editovat] Použité součástky

Mikroprocesor : ATMega8535 , [1]

Displej : Nokia 3310

Naprogramováno v AVR Studiu, pro zápis do mikroprocesoru použit programátor USBasp

Soubor:2ztaplw.jpg Soubor:KonektroLCD.jpg

[editovat] Schéma zapojení

Soubor:schema_kvarda.png Soubor:Znak.jpg‎

[editovat] Třídy funkcí

[editovat] LCD SEND

void lcd_send(unsigned char data, LcdCmdData cd)
{
    // Data/DC are outputs for the lcd (all low)
	LCD_DDR |= LCD_DATA_PIN | LCD_DC_PIN;

    // Enable display controller (active low)
    LCD_PORT &= ~LCD_CE_PIN;

    // Either command or data
    if(cd == LCD_DATA) {         // (active high)
        LCD_PORT |= LCD_DC_PIN;
    } else {                     // (active low)
        LCD_PORT &= ~LCD_DC_PIN;
    }
	
    /*  Send data to display controller. */

    SPDR = data;  // poslání dat přes SPI

	/*  Wait until Tx register empty. */
    while ( (SPSR & 0x80) != 0x80 );

	// Disable display controller
    LCD_PORT |= LCD_CE_PIN;

}

[editovat] LCD GOTO XY


// pro znak
void lcd_goto_xy(unsigned char x, unsigned char y)
{
  
     lcd_send(0x80 |x*6, LCD_CMD);         // posun o znak
     lcd_send(0x40 |y*84, LCD_CMD);        // posun o radek

}


[editovat] Úvodní obrazovka

void Uvodni_obrazovka(void){
	
	lcd_goto_xy(7,1);
	lcd_str("MAM");
	lcd_goto_xy(5,2);
	lcd_str("Projekt");
	lcd_goto_xy(2,3);
	lcd_str("Graf. display");
	lcd_goto_xy(2,4);
	lcd_str("Kvarda, Hnyk");

}

Soubor:uvodni_obrazovka.jpg

[editovat] Vykreslení obrázku

void lcd_image(void)
{
	
    lcd_goto_xy(0,0);      // nastaveni pocatecniho kurzoru
    
    for(unsigned int i=0;i<504;i++) {
	lcd_send(pgm_read_byte(&logoImage[i] ), LCD_DATA);    // posila data po jednotlivych bytech do LCD
    }

Obrázek: LOGO CVUT, pro převod z jpg na hexa posloužil program FASTLCD

const unsigned char logoImage[] PROGMEM  = {

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF8,0xFC,0x3C,0x1C,
0x5C,0xFC,0xFC,0x7C,0x7C,0x3C,0xFC,0xFC,0x3C,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xC0,0x80,0x80,0x80,0x00,0x80,0x8C,0xFC,
0xFC,0xEC,0xEC,0xFF,0xFE,0xFE,0xFF,0x1E,0x1F,0x6F,0x6F,0xEF,0xEE,0x3F,0x1F,0xBF,
0xFB,0xF8,0xD0,0xE0,0x60,0xE0,0xF0,0xF0,0x98,0xF8,0xB8,0x18,0x00,0x00,0x18,0xB8,
0xF8,0xF0,0xB0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE7,
0xFF,0x1F,0x1E,0x1E,0xFF,0xE7,0x05,0x07,0x3F,0xFE,0xE0,0x61,0xE0,0xCF,0x1E,0x18,
0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x10,0x20,0x30,0x31,0xB1,0xF1,0xF0,0x71,
0x31,0xB1,0x99,0xD9,0xDF,0x6F,0x6F,0x6F,0x6F,0x6F,0x34,0xB4,0xB4,0xB6,0xDE,0xDB,
0xDB,0x6C,0xBE,0xBF,0xDF,0xEE,0x77,0xFF,0xFF,0xFF,0xC0,0xE1,0xF7,0xFF,0x7F,0x3E,
0x3C,0x7E,0x7E,0xBF,0xE7,0xC3,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xC0,0xF8,0x3F,0x07,0x00,0xC0,0xF8,0x3F,0x27,0xFF,0xFF,0xFC,0xBE,0x6F,0x7F,0xFF,
0xFF,0xFB,0x83,0x03,0x83,0xC3,0xC3,0xE3,0x63,0x33,0x3F,0x1E,0x1C,0x0C,0x06,0x3F,
0xFF,0xC1,0xC0,0xBE,0xFF,0xE7,0x81,0xF8,0xFC,0x8C,0x06,0xE6,0xF3,0xBB,0x9B,0xC9,
0xCD,0x6D,0x6C,0x36,0x36,0xF3,0xFB,0x19,0x0C,0x06,0x07,0x3F,0xFF,0xFF,0xF7,0xE1,
0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xE1,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,
0x00,0x80,0xF0,0x7E,0xEF,0xF1,0x18,0x18,0x0C,0x0F,0x03,0x00,0x00,0x01,0x01,0x07,
0x0F,0x1F,0x1E,0xFD,0xF8,0x79,0xF9,0xD9,0x79,0x79,0x70,0x38,0x1C,0x0E,0x06,0x02,
0x03,0x03,0x03,0xE3,0x37,0x1E,0x1F,0x1F,0x0B,0x0F,0x0F,0x0F,0x87,0x87,0x87,0x87,
0x8F,0x8F,0x1F,0x3C,0xFC,0xB8,0xF0,0xE0,0xC0,0x01,0x03,0x07,0x06,0x0E,0x7E,0x9E,
0xEE,0x0E,0x0F,0x0F,0x0F,0x0F,0x07,0x07,0x07,0x06,0x03,0x03,0x01,0x01,0x00,0x00,
0x00,0x00,0x00,0xE0,0xFC,0xDF,0xFB,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x1F,0xFE,0xE7,0xFF,0xF8,0xE0,0xE0,0xF0,
0xF0,0xF0,0xF0,0xE0,0xE0,0x80,0x00,0x03,0x07,0x1C,0x78,0xF0,0x00,0x00,0x00,0x07,
0x07,0xF5,0x3D,0x1D,0x0D,0x05,0x01,0x01,0x03,0x03,0x03,0x83,0x83,0x8F,0x9C,0xB8,
0x60,0x60,0x60,0x61,0x63,0x63,0x63,0x62,0xE2,0xC2,0x82,0x03,0x03,0x03,0xFB,0xFF,
0x0F,0x07,0x00,0x00,0xC0,0xF8,0x7F,0x77,0x3E,0x1F,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x3F,
0x37,0xFF,0x3F,0x0B,0x19,0x39,0x31,0x63,0x67,0xC3,0xC6,0xC4,0xCC,0xE4,0x66,0x27,
0xE0,0xE0,0xC0,0x60,0x78,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x7F,0x7F,
0x6F,0xFB,0x7F,0x6F,0x6F,0xCF,0xCE,0xDE,0x8C,0x8C,0x8C,0x8C,0xC6,0xE7,0x71,0x30,
0xE0,0xE0,0xC1,0x7F,0x3E,0x00,0x00,0x00

};
Logo na dipleji                                                    Logo original

Soubor:logo_cvut_aaa.jpg Soubor:Mezera.jpg Soubor:Logo_cvut2_jpg.jpg

[editovat] Zobrazení bodu

/* Zapíše bod na pozici X, Y. */
void lcd_pix(unsigned char x, unsigned char y)
{

unsigned char value;
unsigned char row;
	
    if( x < 0 || x >= 84 || y < 0 || y >= 48 ) return;       // podminka, kvuli preteceni radku

	row = y / 8;                                         // hodnotu y delime 8 , kvuli urceni radku
	value = lcd_buffer[row][x];
	value |= (1 << (y % 8));

    lcd_buffer[row][x] = value;

	lcd_send(0x80 |x, LCD_CMD);              // nastaveni kurzoru kam se bude vypisovat bod
	lcd_send(0x40 |(row), LCD_CMD);
	
	lcd_send(value,LCD_DATA);                // posle hodnotu, ktera zobrazi bod


}

[editovat] Nakreslení čáry

/* Nakreslí čáru */
void lcd_line(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2)
{

int dx, dy, stepx, stepy, fraction;

    /* Calculate differential form */
    /* dy   y2 - y1 */
    /* -- = ------- */
    /* dx   x2 - x1 */

    /* Take differences */
    dy = y2 - y1;
    dx = x2 - x1;

    /* dy is negative */
    if ( dy < 0 ) {
        dy    = -dy;
        stepy = -1;
    } else {
        stepy = 1;
    }

    /* dx is negative */
    if ( dx < 0 ) {
        dx    = -dx;
        stepx = -1;
    } else {
        stepx = 1;
    }

    dx <<= 1;
    dy <<= 1;

    /* Draw initial position */
    lcd_pix( x1, y1 );

    /* Draw next positions until end */
    if ( dx > dy ) {
        /* Take fraction */
        fraction = dy - ( dx >> 1);
        while ( x1 != x2 ) {
            if ( fraction >= 0 ) {
                y1 += stepy;
                fraction -= dx;
            }
            x1 += stepx;
            fraction += dy;

            /* Draw calculated point */
            lcd_pix( x1, y1 );
        }
    } else {
        /* Take fraction */
        fraction = dx - ( dy >> 1);
        while ( y1 != y2 ) {
            if ( fraction >= 0 ) {
                x1 += stepx;
                fraction -= dy;
            }
            y1 += stepy;
            fraction += dx;

            /* Draw calculated point */
            lcd_pix( x1, y1 );
        }
    }



}

[editovat] Zobrazení obdelníku

void lcd_obdelnik(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2)
{
	// lcd_obdelnik (x1,y1,x2,y2)
	//(x1,y1) levy horni roh obdelnika
	//(x2,y2) pravy dolni roh obdelnika

	lcd_line( x1, y1, x2, y1 );
	lcd_line( x1, y1, x1, y2 );
	lcd_line( x1, y2, x2, y2 );
	lcd_line( x2, y1, x2, y2 );

}

[editovat] Zobrazení kruhu

void lcd_kruh(unsigned char x_stred, unsigned char y_stred, unsigned char r)
{

int x=0;
	int y=r;
	int p=3-(2*r);

        lcd_pix( (unsigned char)(x_stred+x),(unsigned char)(y_stred-y));

	for(x=0;x<=y;x++) {
		if (p<0) {
			y=y;
			p=(p+(4*x)+6);
		} else {
			y=y-1;
			p=p+((4*(x-y)+10));
		}

		lcd_pix((unsigned char)(x_stred+x),(unsigned char)(y_stred-y));
		lcd_pix((unsigned char)(x_stred-x),(unsigned char)(y_stred-y));
		lcd_pix((unsigned char)(x_stred+x),(unsigned char)(y_stred+y));
		lcd_pix((unsigned char)(x_stred-x),(unsigned char)(y_stred+y));
		lcd_pix((unsigned char)(x_stred+y),(unsigned char)(y_stred-x));
		lcd_pix((unsigned char)(x_stred-y),(unsigned char)(y_stred-x));
		lcd_pix((unsigned char)(x_stred+y),(unsigned char)(y_stred+x));
		lcd_pix((unsigned char)(x_stred-y),(unsigned char)(y_stred+x));

}
}

[editovat] Zobrazení trojuhelnika

void lcd_trojuhelnik(unsigned char x1, unsigned char y1,unsigned char x2,unsigned char y2, unsigned char x3,unsigned char y3)
{
	// x1 bod souradnice (x1,x1)
	// x2 bod souradnice (x2,x2)
	// x3 bod souradnice (x3,x3)

	lcd_line( x1, y1, x2, y2 );
	lcd_line( x1, y1, x3, y3 );
	lcd_line( x2, y2, x3, y3 );
}

[editovat] Teplomer

void teplomer(void) {
	
	unsigned char temp1[33];	
	ADMUX  |= 0x40;                      //AVCC s externim kapacitorem na AREF
	ADCSRA |= 0xC2; 		     // ADC zapnuto, ADC start, preddelicka 4, pin ADC0
	while (ADCSRA & (1 << ADSC)) {;}     // cekani na prevod

	float b = ADC*0.48583;
	float c = b -273.15;
	lcd_goto_xy(1,3);
    //  itoa(c, temp1, 10);
    //	sprintf(temp1,"%d",c);
        dtostrf(c, 5, 3, temp1); 	     // prevod float na char
	lcd_strnum(temp1);		     // ulozeni na LCD velkymi cisly
	
}

[editovat] Výsledný kód programu

Program navržen v jazyku C v AVR Studiu.

LCD hlavičkový soubor (lcd.h)

/*
** lcd.h
**
** LCD hlavickovy soubor 
** ATMEGA8535
**
** Lukáš Kvarda a Pavel Hnyk
*/

#ifndef _NOKIALCD_H_
#define _NOKIALCD_H_

/* Lcd velikost obrazovky */
#define LCD_X_RES 84
#define LCD_Y_RES 48
#define LCD_CACHE_SIZE ((LCD_X_RES * LCD_Y_RES) / 8)

/* Nastavení pinů pro LCD */
#define LCD_CLK_PIN 	(1<<PB7)
#define LCD_DATA_PIN 	(1<<PB5)
#define LCD_DC_PIN 		(1<<PB0)
#define LCD_CE_PIN 		(1<<PB4)
#define LCD_RST_PIN 	(1<<PB6)
#define LCD_PORT		PORTB
#define LCD_DDR			DDRB


void lcd_init(void);
void lcd_contrast(unsigned char contrast);
void lcd_clear(void);
void lcd_clear_area(unsigned char line, unsigned char startX, unsigned char endX);
void lcd_clear_line(unsigned char line);
void lcd_goto_xy(unsigned char x, unsigned char y);
void lcd_goto_xy_exact(unsigned char x, unsigned char y);
void lcd_chr(char chr);
void lcd_str(char* str);
void lcd_bod(unsigned char x, unsigned char y);
void lcd_pix(char x, char y);
void lcd_line(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2);
void lcd_kruh(unsigned char x_stred, unsigned char y_stred, unsigned char r);
void lcd_obdelnik(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2);
void lcd_image(void);


#endif



LCD knihovna (lcd.c)

/*
** LCD.c
**
** LCD nokia 3310 knihovna funkci
**
** ATMEGA 8535
**
** Vypracoval Lukáš Kvarda a Pavel Hnyk
*/

#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include "lcd.h"
#include "logoImage.h"
#include "tapeta.h"
#include "pixel.h"

/* delay macro function */
#define lcd_delay() for(int i=-32000;i<32000;i++)

/* Command type sent to the lcd */
typedef enum { LCD_CMD  = 0, LCD_DATA = 1 } LcdCmdData;

/* Function prototypes */
void lcd_base_addr(unsigned int addr);
void lcd_send(unsigned char data, LcdCmdData cd);

//char x, y1, y2, samples[84];  
/* The lcd cursor position */
int lcdCacheIdx;
unsigned char char_start; 

/* Abeceda mala pismena */
unsigned char PROGMEM font5x7 [][5] = {
	{ 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp
    { 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
    { 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
    { 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
    { 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
	{ 0x32, 0x34, 0x08, 0x16, 0x26 },   // %
    { 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
    { 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
    { 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
    { 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
    { 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
    { 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
    { 0x00, 0x00, 0x50, 0x30, 0x00 },   // ,
    { 0x10, 0x10, 0x10, 0x10, 0x10 },   // -
    { 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
    { 0x20, 0x10, 0x08, 0x04, 0x02 },   // /
    { 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
    { 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
    { 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
    { 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
    { 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
    { 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
    { 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
    { 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
    { 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
    { 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
    { 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
    { 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
    { 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
    { 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
    { 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
    { 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
    { 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
    { 0x7E, 0x11, 0x11, 0x11, 0x7E },   // A
    { 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
    { 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
    { 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
    { 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
    { 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
    { 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
    { 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
    { 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
    { 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
    { 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
    { 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
    { 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
    { 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
    { 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
    { 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
    { 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
    { 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
    { 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
    { 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
    { 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
    { 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
    { 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
    { 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
    { 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
    { 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
    { 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
    { 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55
    { 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
    { 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
    { 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
    { 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
    { 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
    { 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
    { 0x38, 0x44, 0x44, 0x44, 0x20 },   // c
    { 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
    { 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
    { 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
    { 0x0C, 0x52, 0x52, 0x52, 0x3E },   // g
    { 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
    { 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
    { 0x20, 0x40, 0x44, 0x3D, 0x00 },   // j
    { 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
    { 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
    { 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
    { 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
    { 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
    { 0x7C, 0x14, 0x14, 0x14, 0x08 },   // p
    { 0x08, 0x14, 0x14, 0x18, 0x7C },   // q
    { 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
    { 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
    { 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
    { 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
    { 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
    { 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
    { 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
    { 0x0C, 0x50, 0x50, 0x50, 0x3C },   // y
    { 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
    { 0x00, 0x00, 0x02, 0x05, 0x02 },   // ° stupeň 
	{ 0x08, 0x1C, 0x3E, 0x7F, 0x00 }, 	// < Filled
	{ 0x08, 0x7C, 0x7E, 0x7C, 0x08 },   // Arrow up
	{ 0x10, 0x3E, 0x7E, 0x3E, 0x10 },   // Arrow down	
	{ 0x3E, 0x3E, 0x3E, 0x3E, 0x3E },   // Stop
	{ 0x00, 0x7F, 0x3E, 0x1C, 0x08 }    // Play
};

// Cisla velka psimena

unsigned char PROGMEM number [13][3][16]  = {

{{0,128,192,224,224,96,224,224,  //'0'
192,128,0,0,0,0,0,0}
,
{112,255,255,1,0,0,0,0,
255,255,254,0,0,0,0,0}
,
{0,15,31,60,56,48,56,56,
31,15,3,0,0,0,0,0}
},
{
{0,0,0,0,128,224,224,0, 		   //'1'
0,0,0,0,0,0,0,0}
,
{0,0,3,3,3,255,255,0,
0,0,0,0,0,0,0,0}
,
{0,0,56,56,56,63,63,56,
56,56,0,0,0,0,0,0}
},
{
{0,192,192,224,96,96,224,224,   //'2'
192,128,0,0,0,0,0,0}
,
{0,1,0,0,128,192,224,249,
63,31,0,0,0,0,0,0}
,
{0,60,62,63,63,59,57,56,
56,56,56,0,0,0,0,0}
},
{
{0,192,224,224,96,96,224,224,   //'3'
192,192,0,0,0,0,0,0}
,
{0,1,0,0,48,48,56,125,
239,207,0,0,0,0,0,0}
,
{0,28,56,56,48,48,56,60,
31,15,1,0,0,0,0,0}
},
{
{0,0,0,0,0,128,192,224, 		   //'4'
224,0,0,0,0,0,0,0}
,
{224,240,248,222,207,199,193,255,
255,192,192,0,0,0,0,0}
,
{0,0,0,0,0,0,0,63,
63,0,0,0,0,0,0,0}
},
{
{0,224,224,224,224,224,224,224,	//'5'
224,224,224,0,0,0,0,0}
,
{0,63,63,63,56,56,48,112,
240,224,0,0,0,0,0,0}
,
{0,28,56,56,48,48,56,60,
31,15,1,0,0,0,0,0}
},
{
{0,0,128,192,192,224,96,96,		//'6'
224,224,0,0,0,0,0,0}
,
{224,254,255,55,57,24,24,56,
240,240,192,0,0,0,0,0}
,
{0,15,31,28,56,48,48,56,
31,15,7,0,0,0,0,0}
},
{
{0,224,224,224,224,224,224,224,		 //'7'
224,224,224,0,0,0,0,0}
,
{0,0,0,0,128,224,248,126,
31,7,1,0,0,0,0,0}
,
{0,0,56,62,31,7,1,0,
0,0,0,0,0,0,0,0}
},
{
{0,128,192,224,224,96,96,224,		 //'8'
192,192,0,0,0,0,0,0}
,
{0,207,255,127,56,48,112,112,
255,239,199,0,0,0,0,0}
,
{3,15,31,60,56,48,48,56,
31,31,15,0,0,0,0,0}
},
{
{0,128,192,224,224,96,224,224,		 //'9'
192,128,0,0,0,0,0,0}
,
{12,63,127,241,224,192,192,225,
255,255,254,0,0,0,0,0}
,
{0,0,56,48,48,56,56,30,
15,7,0,0,0,0,0,0}
},
{

{0,0,0,0,0,0,0,0,	  		  		 //'.'
0,0,0,0,0,0,0,0}
,
{0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0}
,
{60,60,60,0,0,0,0,0,
0,0,0,0,0,0,0,0} 
},
{
{0,0,0,0,0,0,0,0,   					 //'+'
0,0,0,0,0,0,0,0}
,
{0,0,64,64,64,64,64,254,
254,64,64,64,64,64,0,0}
,
{0,0,0,0,0,0,0,15,
15,0,0,0,0,0,0,0}
},
{
{0,0,0,0,0,0,0,0, 	   				 //'-'
0,0,0,0,0,0,0,0}
,
{0,64,64,64,64,64,64,0,
0,0,0,0,0,0,0,0}
,
{0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0}
}}; 



// INICIALIZACE LCD
void lcd_init(void)
{
    // Pull-up on reset pin
    LCD_PORT |= LCD_RST_PIN;
	
	// Set output bits on lcd port
	LCD_DDR |= LCD_RST_PIN | LCD_CE_PIN | LCD_DC_PIN | LCD_DATA_PIN | LCD_CLK_PIN;
    
	// Wait after VCC high for reset (max 30ms)
    _delay_ms(15);
    
    // Toggle display reset pin
    LCD_PORT &= ~LCD_RST_PIN;
    lcd_delay();
    LCD_PORT |= LCD_RST_PIN;

    // Disable LCD controller
    LCD_PORT |= LCD_CE_PIN;

    lcd_send(0x21, LCD_CMD);  // LCD Extended Commands
    lcd_send(0xC8, LCD_CMD);  // Set LCD Vop(Contrast)
    lcd_send(0x06, LCD_CMD);  // Set Temp coefficent
    lcd_send(0x13, LCD_CMD);  // LCD bias mode 1:48
    lcd_send(0x20, LCD_CMD);  // Standard Commands, Horizontal addressing
    lcd_send(0x0C, LCD_CMD);  // LCD in normal mode
    
    // Clear lcd
    lcd_clear();
	
	// For using printf
//	fdevopen(lcd_chr, 0);
}

/* Set display contrast. Note: No change is visible at ambient temperature */
void lcd_contrast(unsigned char contrast)
{
	lcd_send(0x21, LCD_CMD);				// LCD Extended Commands
    lcd_send(0x80 | contrast, LCD_CMD);		// Set LCD Vop(Contrast)
    lcd_send(0x20, LCD_CMD);				// LCD std cmds, hori addr mode
}

/* Vymazání dipleje */
void lcd_clear(void)
{
	lcdCacheIdx = 0;
	
	lcd_base_addr(lcdCacheIdx);
	
    // Set the entire cache to zero and write 0s to lcd
    for(int i=0;i<LCD_CACHE_SIZE;i++) {
		lcd_send(0, LCD_DATA);
    }
}

/* Clears an area on a line */
void lcd_clear_area(unsigned char line, unsigned char startX, unsigned char endX)
{  
    // Start and end positions of line
    int start = (line-1)*84+(startX-1);
    int end = (line-1)*84+(endX-1);
	
	lcd_base_addr(start);
    
    // Clear all data in range from cache
    for(unsigned int i=start;i<end;i++) {
        lcd_send(0, LCD_DATA);
    }
}

/* Clears an entire text block. (rows of 8 pixels on the lcd) */
void lcd_clear_line(unsigned char line)
{
    lcd_clear_area(line, 1, LCD_X_RES);
}

/* Nastavení pozice kurzoru odpovídající základní velikosti textu */
void lcd_goto_xy(unsigned char x, unsigned char y)
{
    lcdCacheIdx = (x-1)*6 + (y-1)*84;
}


void lcd_goto_xy_megaFONT(unsigned char x, unsigned char y)
{
    lcdCacheIdx = (x-1)*11 + (y-1)*84;
}


/* Sets cursor location to exact xy pixel location on the lcd */
void lcd_goto_xy_exact(unsigned char x, unsigned char y)
{
    lcdCacheIdx = (x-1) + (y-1)*84;
}


// Nastavení základních adres LCD
void LCD_gotoXY ( unsigned char x, unsigned char y )
{
    lcd_send(0x80 | x , LCD_CMD);   //column
	lcd_send(0x40 | y, LCD_CMD);   //row
}



/* Displays a character at current cursor location */
void lcd_chr(char chr)
{
	lcd_base_addr(lcdCacheIdx);

    // 5 pixel wide characters and add space
    for(unsigned char i=0;i<5;i++) {
		lcd_send(pgm_read_byte(&font5x7[chr-32][i]) << 1, LCD_DATA);
    }
	lcd_send(0, LCD_DATA);
	
	lcdCacheIdx += 6;
}


void lcd_chrnum(unsigned char ch)
{

	unsigned char i;

 if(ch == '.')
    ch = 10;
   else if (ch == '+')
    ch = 11;
   else if (ch == '-')
    ch = 12;
   else
    ch = ch & 0x0f;
   
   for(i=0;i<3;i++)
   {	
	 LCD_gotoXY (4 + char_start, i+2); 

    for(unsigned char j=0;j<16;j++){ 
		lcd_send(pgm_read_byte(&number[ch][i][j]), LCD_DATA);
    }}
	lcd_send(0, LCD_DATA);
	
	 if(ch == '.') 
     char_start += 5;
   else
     char_start += 12; 
}


/* Displays string at current cursor location and increment cursor location */
void lcd_str(char *str)
{
    while(*str) {
        lcd_chr(*str++);
    }
}


void lcd_strnum(char *str)
{  char_start = 0;
	
    while ( *str)  {
        lcd_chrnum(*str++);
		LCD_gotoXY(char_start+6, 3); 
    }
}

// Set the base address of the lcd
void lcd_base_addr(unsigned int addr) {
	lcd_send(0x80 |(addr % LCD_X_RES), LCD_CMD);
	lcd_send(0x40 |(addr / LCD_X_RES), LCD_CMD);
}

/* Posílání dat do kontroléru dipleje */
void lcd_send(unsigned char data, LcdCmdData cd)
{
    // Data/DC are outputs for the lcd (all low)
	LCD_DDR |= LCD_DATA_PIN | LCD_DC_PIN;

    // Enable display controller (active low)
    LCD_PORT &= ~LCD_CE_PIN;


    // Either command or data
    if(cd == LCD_DATA) {         // (active high)
        LCD_PORT |= LCD_DC_PIN;
    } else {                     // (active low)
        LCD_PORT &= ~LCD_DC_PIN;
    }
	
    /*  Send data to display controller. */

	SPCR = 0x50;
    SPDR = data;  // poslání dat přes SPI

	/*  Wait until Tx register empty. */
    while ( (SPSR & 0x80) != 0x80 );

	// Disable display controller
    LCD_PORT |= LCD_CE_PIN;


}


void lcd_image(void)
{
	lcdCacheIdx = 0;
	lcd_base_addr(lcdCacheIdx);

    for(unsigned int i=0;i<504;i++) {
		lcd_send(pgm_read_byte(&logoImage[i] ), LCD_DATA);
    }

	
}

void lcd_tapeta(void)
{
	lcdCacheIdx = 0;
	lcd_base_addr(lcdCacheIdx);

    for(unsigned int i=0;i<504;i++) {
		lcd_send(pgm_read_byte(&tapeta[i] ), LCD_DATA);
    }

	
}

void lcd_gotoxy(unsigned char x, unsigned char y)
{
	lcd_send(x | 0x80, LCD_CMD);
	lcd_send((y & 0x07) | 0x40, LCD_CMD);
}



/* Zapíše bod na pozici X, Y. */
void lcd_pix (char x, char y)  
 {  
      char data;  
      if ((x > 83) || (y > 47)) return;  
      data = 0x01<<(y%8);  
      lcd_gotoxy(x, (y>>3));
      lcd_send(data, LCD_DATA);  
 }



void erase_column(char x)
{
	char line;
	if(x>83)	return;
	for(line=0; line<6; line++)
	{
		lcd_gotoxy(x, line);
		lcd_send(0x00, LCD_DATA);
	}
}

/* Nakreslí vertikální čáru */
void lcd_vertical_line (char x, char y1, char y2)
{
	char i, temp, line1, line2, data;
	if( (x>83) || (y1>47) || (y2>47) )	return;	//exit if out of range
	if(y1>y2)
	{
		temp = y1;
		y1 = y2;	//swap variables
		y2 = temp;
	}
	line1 = y1>>3;	//divide by 8
	line2 = y2>>3;
	for(i=line1; i<=line2; i++)
	{
		data = 0xff;
		lcd_gotoxy(x,i);
		if(i==line1)
		{
			data = 0;
			temp = 8 - (y1 % 8);
			while(temp--)	data |= (0x80>>temp);
		}
		if(i==line2)
		{
			temp = 7 - (y2 % 8);
			while(temp--)	data &= ~(0x80>>temp);
		}
		lcd_send(data, LCD_DATA);
	}
}

/* Nakreslí čáru */
void lcd_line(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2)
{

int dx, dy, stepx, stepy, fraction;

    /* Calculate differential form */
    /* dy   y2 - y1 */
    /* -- = ------- */
    /* dx   x2 - x1 */

    /* Take differences */
    dy = y2 - y1;
    dx = x2 - x1;

    /* dy is negative */
    if ( dy < 0 ) {
        dy    = -dy;
        stepy = -1;
    } else {
        stepy = 1;
    }

    /* dx is negative */
    if ( dx < 0 ) {
        dx    = -dx;
        stepx = -1;
    } else {
        stepx = 1;
    }

    dx <<= 1;
    dy <<= 1;

    /* Draw initial position */
    lcd_pix( x1, y1 );

    /* Draw next positions until end */
    if ( dx > dy ) {
        /* Take fraction */
        fraction = dy - ( dx >> 1);
        while ( x1 != x2 ) {
            if ( fraction >= 0 ) {
                y1 += stepy;
                fraction -= dx;
            }
            x1 += stepx;
            fraction += dy;

            /* Draw calculated point */
            lcd_pix( x1, y1 );
        }
    } else {
        /* Take fraction */
        fraction = dx - ( dy >> 1);
        while ( y1 != y2 ) {
            if ( fraction >= 0 ) {
                x1 += stepx;
                fraction -= dy;
            }
            y1 += stepy;
            fraction += dx;

            /* Draw calculated point */
            lcd_pix( x1, y1 );
        }
    }


}


	

void lcd_obdelnik(unsigned char x1, unsigned char y1,unsigned char x2, unsigned char y2)
{
	// lcd_obdelnik (x1,y1,x2,y2)
	//(x1,y1) levy horni roh obdelnika
	//(x2,y2) pravy dolni roh obdelnika

	lcd_line( x1, y1, x2, y1 );
	lcd_vertical_line( x1, y1, y2 );
	lcd_line( x1, y2, x2, y2 );
	lcd_vertical_line( x2, y1, y2 );

}


void lcd_kruh(unsigned char x_stred, unsigned char y_stred, unsigned char r)
{

int x=0;
	int y=r;
	int p=3-(2*r);

        lcd_pix( (unsigned char)(x_stred+x),(unsigned char)(y_stred-y));

	for(x=0;x<=y;x++) {
		if (p<0) {
			y=y;
			p=(p+(4*x)+6);
		} else {
			y=y-1;
			p=p+((4*(x-y)+10));
		}

		lcd_pix((unsigned char)(x_stred+x),(unsigned char)(y_stred-y));
		lcd_pix((unsigned char)(x_stred-x),(unsigned char)(y_stred-y));
		lcd_pix((unsigned char)(x_stred+x),(unsigned char)(y_stred+y));
		lcd_pix((unsigned char)(x_stred-x),(unsigned char)(y_stred+y));
		lcd_pix((unsigned char)(x_stred+y),(unsigned char)(y_stred-x));
		lcd_pix((unsigned char)(x_stred-y),(unsigned char)(y_stred-x));
		lcd_pix((unsigned char)(x_stred+y),(unsigned char)(y_stred+x));
		lcd_pix((unsigned char)(x_stred-y),(unsigned char)(y_stred+x));

}
}


Hlavní program

/*
** Main.c
**
** LCD DISPLEJ NOKIA 3310
** ATMEGA 8535

** Vypracoval Lukáš Kvarda a Pavel Hnyk
	datum 12.5. 2011 

*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "lcd.h"
#define F_CPU 4000000UL  //nadefinovaná frekvence krystalu 


int main(void)
{	
////////////////////////////////
// Inicializace úvodní obrazovky
	
void Uvodni_obrazovka(void){
	
	
	lcd_goto_xy(7,1);
	lcd_str("MAM");
	lcd_goto_xy(5,2);
	lcd_str("Projekt");
	lcd_goto_xy(2,3);
	lcd_str("Graf. display");
	lcd_goto_xy(2,4);
	lcd_str("Kvarda, Hnyk");

}	

// Vykreslení čáry

void line(void){
	
		lcd_line(0, 10, 20, 30);

}

////////////////////////////
// Vykreslení obdelníka

void obdelnik(void){
			
	// lcd_obdelnik (x1,y1,x2,y2)
	// (x1,y1) levy horni roh obdelnika
	// (x2,y2) pravy dolni roh obdelnika
		
		lcd_obdelnik(0,0,30,30);
    	
}

////////////////////////////
// Vykreslení kruhu

void kruh(void){
	// lcd_kruh(stred x,stred y ,polomer);
		lcd_kruh(30,30,10);
    	
}

////////////////////////////
// Vykreslení trojúhelníka

void trojuhelnik(void){
			
	// lcd_trojuhelnik(bod1 x1,bod1 y1,bod2 x2,bod2 y2,bod3 x3,bod3 y3);
		lcd_trojuhelnik(40,0,0,20,50,20);
    	
}

////////////////////////////
// Vykreslení loga CVUT

void logo(void){
    lcd_image();

}
	
	lcd_init();

// nekonečná smyčka
while(1){					
lcd_clear();
lcd_contrast(0x40);		// nastavení úrovně kontrastu
	Uvodni_obrazovka();
		_delay_ms(1000);
		lcd_clear();
	line();
		_delay_ms(1000);
		lcd_clear();
	obdelnik();
		_delay_ms(1000);
		lcd_clear();
	kruh();
		_delay_ms(1000);
		lcd_clear();
	trojuhelnik();
		_delay_ms(1000);
		lcd_clear();
	logo();
		_delay_ms(1000);

}

}

[editovat] 1. Domácí úkol

[editovat] Zadání

Zvolte vhodné zapojení a procesor a v assembleru naprogramujte 2 na sobě nezávislé PWM regulace osvětlení do auta. Jedna je pro vnitřní osvětlení, po sepnutí dveřního kontaktu nastaví okamžitě plný svit, po rozpojení ještě asi 5 s plný svit a následuje asi 2 sekundy dosvit s poklesem od maxima do nuly, druhá PWM je pro regulované osvětlení palubní desky, vstup potenciometr, výstup výkonová PWM regulace asi 10 % až 100 %. Napájecí napětí auta je 12 V, špičky rušení mohou dosáhnout až 20 V.

Vypracoval : Lukáš Kvarda, Pavel Hnyk


[editovat] ASM kód

.INCLUDE "m88def.inc"

.EQU PWM_PULSES = 36	; value for 27.8 kHz PWM
;.EQU PWM_PULSES = 45	; value for 22.2 kHz PWM




.ORG 0x0000 
	rjmp Main ; Reset Handler

.ORG 0x0004 
	rjmp isr1 ; PCINT1 Handler



; Main program start

Main: 

; Stack pointer init:
	ldi r16,high(RAMEND); Main program start
	out SPH,r16 ; Set Stack Pointer to top of RAM
	ldi r16,low(RAMEND)
	out SPL,r16


; Hardware initialization

; Keyboard init:
	cbi DDRC, 2 ; set inputs for keyboard (COL1-3)
	cbi DDRC, 3
	cbi DDRC, 4

	sbi PORTC, 2 ; set internal Pull-Ups for keyboard
	sbi PORTC, 3
	sbi PORTC, 4

	sbi DDRD, 0 ; set driving outputs for keyboard
	sbi DDRD, 1 ; (ROW1-ROW4)
	sbi DDRD, 2
	sbi DDRD, 3

	cbi PORTD, 0	; log. 0 on all rows
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3



; Timer controlled PWM init:
;
; There are registers TCCR0A and TCCR0B for config, DDRD for output bit
; enabling, OCR0A for counter lenght and OCR0A for pulse "high" lenght.
; Register TIMSK0 controlls interrupts - not used, 0x00 by default 

PWM_INIT:
	ldi R17, 0b00100011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17			; 
	ldi R17, 0b00001001	; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1)
	out TCCR0B, R17
	ldi R17, PWM_PULSES	; load number of clock pulses for 1 PWM period
	out OCR0A, R17   

	sbi DDRD, 5	; set pin 11 as PWM output OC0B (PD5 pin)



; Keyboard interrupt setup
;
; Activation of pin change interrupt - PROBLEM!!! PCICR and PCIMSK are 
; extended I/O registers (0x68 and 0x6C), and must be handled as 
; a memory location

ldi r26, PCICR ; load address of PCICR in Y low
clr r27 ; load high byte with 0
ldi r16,0b00000010 ; activate PCINT1
st X, r16 ; store new PCINT1

ldi r26, PCMSK1 ; load address of PCMSK1 in Y low
clr r27 ; load high byte with 0
ldi r16,0b00011100 ; allow pin change interrupt on portC bits 2,3,4
st X, r16 ; store new PCMSK1

sei ; Enable interrupts


; Set sleep mode of the CPU
; SMCR: 0,0,0,0,SM2,SM1,SM0,SE   SM2..0: Sleep Mode Select Bits, SE: Sleep enabled)

	ldi r16,0b00000001 ; Idle mode 
	out SMCR,r16 ; Sleep mode set


; Sleep loop, wake up by the Interrupt, return with RETI back to sleep loop

loop:
	sleep ; now AVR sleeps
	nop ; return from Interrupt to this instruction
	rjmp loop ; and sleep again


; PCINT0 Service Routine:
;
; To do: *** rpm reading, regulation, etc.


isr1:
	rcall KEYPRESS

	reti ; return from Interrupt


; Keyboard decoding:

SEPNUTI:

	ldi R18, 0xFF	; load number of clock pulses for 1 PWM period
	out OCR0B, R18	
	RCALL WAIT
	SMYCKA:
		out OCR0B, R18		   ; vystup PWM - pripojena dioda - "POMALE ZHASINANI"
		CPSE R0,R18
 	    DEC R18
		RCALL SMALLWAIT        ; cekani mezi dekrementací
		ldi R20,0x00           ; pro porovnání jestli R18 = R20 = 0x00
        CP R18,R20
    BRNE SMYCKA

	rjmp	KEYRET


REGULACE:
   //  na AREF privedeno 5V, maximum PWM 0xFF, AVCC = 5V
	cbi	DDRC,0	
	sbi PORTC, 0
	ldi R17,0x25	
	ldi R22,0xE1

	;The AVR has two different methods for accessing the Special Function Input/Output Registers (SFIOR).
	;The IN/OUT instructions only work with SFIOR addresses 0 to 0x3F. You need to use LDS/STS for higher SFIOR addresses. 
	sts ADMUX,R17	; kanal ADC5 , zarovnani vysledku vlevo, AREF	( vsechno nastaveno hexa cislem 0x27) 	
	sts ADCSRA,R22	; preddelicka kmitoctu 4, adc enable , adc start konverze, adc free running ( vsechno nastaveno hexa cislem 0xE2) 	
	
	lds	R25,ADCH      ; ulozeni vysledku ADC do registru hornich 8 bitu
	lds	R26,ADCL	  ; ulozeni vysledku ADC do registru dolnich 8 bitu
	out OCR0A, R25   ; poslani vysledku na PWM vystup  hornich 8 bitu   
    rjmp	KEYRET

WAIT:
	LDI	R16, 99	; LDI - Load Immediate     5sec wait
WAIT1:	
	INC	R1
	BRNE	WAIT1
	INC	R2
	BRNE	WAIT1
	DEC	R16
	BRNE	WAIT1
	RET

SMALLWAIT:
	LDI	R16, 10	; LDI - Load Immediate     2sec wait
WAIT2:	
	INC	R1
	BRNE	WAIT2
	DEC	R16
	BRNE	WAIT2
	RET


KEYPRESS:
KEY0:
	sbi 	PORTD, 0
	sbi 	PORTD, 1
	sbi 	PORTD, 2
	cbi 	PORTD, 3	;log. 0 to the row with *, 0, #, D	
	sbic	PINC, 3
	rjmp	KEY1
	rjmp    SEPNUTI
KEY1:
	cbi 	PORTD, 0	;log. 0 to the row with 1, 2, 3, A
	sbi 	PORTD, 1	;log. 1 on another three
	sbi 	PORTD, 2
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEYRET
	rjmp    REGULACE

KEYRET:
	cbi PORTD, 0	; log. 0 on all rows for next key press catch
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3
	ret

Osobní nástroje