ATmega8 - Feszültség mérő

2013-02-05

 

A kapcsolás megegyezik az ADC kezeléshez használttal. A tényleges mérő készülék esetében analóg bemeneti áramkört kell az uC bemenete elé tenni, ami adott esetben lehet egy feszültség osztó is.

Az asztalon a megszokott kuszaság.

Két újdonság van a programban. Az egyik a fix pontos kiíró rutin az LCD-re. Ezi tesz lehetővé, hogy 10-es számrendszerben, a számunkra megszokott formában (nem hexa :) írja ki a prgram a mért eredményeket. Végre rájöttem, mire is használható az LCD-n a betük kiírási irányának megváltoztatására szolgáló parancs. A konvertálásnál előszőr a legkisebb helyiértékű digit áll elő. Ha hátulról kezdem balra felé kiíratni a digiteket, akkor nem kell hozzá külön buffer. A függvénybe tettem kezdő nulla elnyomást is. A másik az ADC megszakítás vektorban található számoló képlet. A program elején definiálhatjuk a számításhoz használt értékeket. A FELBONTAS az AD által legnagyobb mérhető érték. Az OSZTAS a legnagyobb megjelenítendő érték (1000, 2000 ....). A TIZEDESPONT pedig nyiván a tizedesjegyek száma. A képletben azért használtam long értékeket, mert így akkor is jó lehet, ha 10, 16 vagy több bit-es AD-t használunk.



/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   http://www.tkiraaly.hu
*   Date         -  2013.02.04.
*   Chip         -  Atmel ATmega8 & HD44780
*   Compiler     -  avr-gcc (WinAVR)
*
*   ATmega8 feszultseg mero
*   
********************************************************************************
*    LCD bekotese:
*
*    14   LCD D7       - AVR PD7  - 13
*    13   LCD D6       - AVR PD6  - 12
*    12   LCD D5       - AVR PD5  - 11
*    11   LCD D4       - AVR PD4  -  6
*    10   LCD D3
*     9   LCD D2
*     8   LCD D1
*     7   LCD D0
*     6   LCD E        - AVR PC2  - 25
*     5   LCD RW       - GND
*     4   LCD RS       - AVR PC3  - 26
*     3   LCD KONTR    - 10 kOhm trim.
*     2   LCD VDD      - +5V
*     1   LCD VSS      - GND
*
*
*    Analog resz:
*
*                        AVR AVCC - 20 - 100nF - GND / 51R - VCC 
*                        AVR AREF - 21 - 100nF - GND
*                        AVR ADC0 - 23 - 100nF - GND / 1K poti VCC/GND
*
*******************************************************************************/

#define F_CPU                4000000             // orajel (MHz)

#define OSZTAS               1000UL
#define TIZEDESPONT          2
#define FELBONTAS            255UL




#include "tkiraaly_atmega8.h"
#include <util/delay.h>
#include <avr/pgmspace.h>




#define LED                  0
#define LED_ENABLE           BS( DDRB, LED)
#define LED_BE               BC( PORTB, LED)
#define LED_KI               BS( PORTB, LED)

#define LCD_E                2
#define LCD_E_ENABLE         BS( DDRC,  LCD_E)
#define LCD_E_0              BC( PORTC, LCD_E)
#define LCD_E_1              BS( PORTC, LCD_E)

#define LCD_RS               3
#define LCD_RS_ENABLE        BS( DDRC,  LCD_RS)
#define LCD_RS_UTASITAS      BC( PORTC, LCD_RS)
#define LCD_RS_ADAT          BS( PORTC, LCD_RS)

#define LCD_PORT             PORTD               // felso 4 bit+ E, RS
#define LCD_PORT_ENABLE      DDRD= 0B11110000




void lcd_init4( void);                           // LCD inicializalasa 4 bitre
void lcd_putc( UC);                              // betu kiirasa
void lcd_putcmd( UC);                            // parancskod kiadasa
void lcd_yx( UC, UC);                            // kurzor pozicioja 0..3/0..15
void lcd_cls( void);                             // kepernyo torles
void lcd_puts( const char *);                    // string kiirasa
void lcd_fixdp( int, UC, UC);                    // fix pontos kiiras LCD-re 




ISR( ADC_vect)			                             // IT, ha AD meres lefutott
{
   lcd_yx( 1, 10);
   lcd_fixdp( (int)( (unsigned long)ADCH * OSZTAS/ FELBONTAS), 4, 1);
}




int main( void)
{
   lcd_init4();
   lcd_cls();
   lcd_yx( 0, 1);
   lcd_puts( PSTR( "KT - V meter"));
   lcd_yx( 1, 2);
   lcd_puts( PSTR( "Ube=     V"));

   ADMUX= VREF_INT_2_56V+ ADC_8BIT+ IN_ADC0;
   ADCSRA= ADC_ENABLE+ ADC_IT_ENABLE+ ADC_CP64;  

   LED_ENABLE;
   LED_BE;

   IT_ENABLE;

   for(;;)
   {
      START_ADC;                                 // meres 0,5 sec-enkent
      _delay_ms( 200);
   }
   return 0;
}




void lcd_init4( void)                            // LCD inicializalasa 4 bitre
{
   LCD_PORT_ENABLE;
   LCD_E_ENABLE;
   LCD_RS_ENABLE;
   _delay_ms( 15);
   LCD_RS_UTASITAS;
   LCD_PORT= 0B00100000;                         // 4 bit interface
   LCD_E_1;
   LCD_E_0;
   _delay_ms( 5);
   LCD_E_1;
   LCD_E_0;
   _delay_us( 120);
   lcd_putc( 0B00101000);                        // 4 bit interface, 2 sor, 5x8 pontos betu
   lcd_putc( 0B00101000);                        // 2x kell kiadni, vagy LCD D3-t VDD-re kell kotni
   lcd_putc( 0B00001100);                        // kijelzes be, cursor ki
   lcd_putc( 0B00000110);                        // kiiras jobbra
   LCD_RS_ADAT;
}




void lcd_putcmd( UC cmd)                         // parancskod kiadasa
{
   LCD_RS_UTASITAS;
   lcd_putc( cmd);
   LCD_RS_ADAT;
}




void lcd_putc( UC c)                             // egy betu kiiras
{
   LCD_E_1;                                      // felso 4 bit
   LCD_PORT= ( LCD_PORT & 0x0F) | ( 0xF0 & c);
   LCD_E_0;
   LCD_E_1;                                      // also 4 bit
   LCD_PORT= ( LCD_PORT & 0x0F) | ( 0xF0 & c << 4);
   LCD_E_0;
   _delay_us( 37);                               // var 37 usec  
}




void lcd_yx( UC sor, UC betu)                    //  kurzor pozicionalasa 0..3/0..15
{
   UC cim= 0x80;                                 // parancs kodja
   if (sor & 0B00000001) cim+= 64;               // 1. es 3. sor
   if (sor & 0B00000010) cim+= 20;               // 2. es 3. sor
   cim+= betu & 0x0F; 
   lcd_putcmd( cim);
}




void lcd_cls( void)                              // kepernyo torles
{
   lcd_putcmd( 0x01);
   _delay_ms( 2);
}




void lcd_puts( const char *s)                    // string kiiras
{
   register unsigned char c;
   while ( ( c= pgm_read_byte( s++))) lcd_putc( c);
}




void lcd_fixdp(                                  // fix pontos kiiras LCD-re  
                int n,                           // ertek
                UC digit,                        // szamjegyek szama
                UC dp)                           // tizedespont helye
{
    UC i;                                        // szamlalo
    UC c;                                        // kiirando karakter
    i= digit;
    if( dp)                                      // ha van tizedes pont
    {
       i++;                                      // +1 karakter
       dp= i- dp;                                // tizedespont helye
    }
    lcd_putcmd( 0B00000100);                     // LCD balra ir
    for( ; i; i--)
    {
       if( i == dp)
       {
          c= '.';       
       }
       else
       {
          c= '0'+ n% 10;
          if( ( n == 0) && ( ( i+ 1) < dp)) c= ' ';  // elejen 0 elnyomas
          n/= 10;       
       }
       lcd_putc( c);
    }
    lcd_putcmd( 0B00000110);                     // LCD jobbra ir
}

Itt a vége, fuss el véle, legytek az én vendégeim, innen letölthetitek a hozzávalókat összecsomagolva.