Programmation du PIC16F877A - 2e partie

Dans cette deuxième partie consacrée à la programmation du microcontrôleur PIC 16F877A, on se propose de mettre en œuvre le convertisseur analogique numérique.

Un potentiomètre de 470 kΩ va délivrer la tension analogique à convertir. Il est alimenté en +5 Volts. Le point milieu du potentiomètre est branché sur l’entrée analogique AN7 (broche RE2) du microcontrôleur. Puis, un écran LCD 2 lignes 16 caractères va afficher ces valeurs de tension. Il sera branché sur le port B du microcontrôleur.

L'outil de simulation du fonctionnement est Proteus, on se servira de l'environnement de dévéloppement MPLAB X en langage C.

Matériel nécessaire:

  • Un afficheur LCD 2 lignes 16 caractères;
  • Un potentiomètre multitours ajustable: 470KΩ;
  • Un potentiomètre multitours ajustable: 10KΩ;
  • Un microcontrôleur: PIC16F877A;
  • Un quartz: 20MHz;
  • Deux condensateurs: 27pF
  • Une plaque à essais, et des fils de câblage;

 

Le schéma du montage

schema can pic16f877a

L' objet « Voltmètre », ajouté dans le schéma ci-dessus, ne sera utile que pour la simulation.

 

Le microcontrôleur PIC16F877A possède un convertisseur analogique numérique, 10 bits capable de gérer jusqu’à huit entrées analogiques. Ce module est  configurable par des registres internes.

 

Le convertisseur analogique numérique (CAN)

Le module CAN dispose de quatre registres internes :

  • ADRESH et ADRESL (Analog to Digital Result High Register, et Analog to Digital Result Low Register). Ces deux registres contiennent le résultat numérique sur 10 bits à la fin de la conversion.  ADRESH contient la partie haute, tandis que ADRESL contient la partie basse.
  • ADCON0 : (A/D Control Register0), registre de contrôle 0, du convertisseur ;
  • ADCON1 : (A/D Control Register1), registre de contrôle 1, du convertisseur.

Le registre ADCON0 contrôle les opérations du module de conversion analogique numérique, tandis que le registre ADCON1 assure la configuration des broches du port, qui peuvent être configurés soit comme des entrées analogiques, soit comme des E/S numériques.

 

Rôle des bits du registre ADCON0

Il faudra consulter la documentation technique du PIC16F877A, pour voir sa constitution interne.

Les bits 7 et 6 : ADCS1 et ADCS0  sont des bits de sélection de l’horloge du conversion.

Les bits 5, 4 et 3 : CHS2, CHS1 et CHS0 effectuent la sélection de la voie analogique à convertir.

Le bit  2 : GO/DONE signale l’état de la conversion. Quand il vaut 1, la conversion est en cours, et lorsqu’il vaut 0 il n’y a pas de conversion.

Le bit 1 : n’est pas implémenté et est lu comme un 0.

Le bit 0 : ADON lorsque ce bit est égal à 1, le module de conversion analogique numérique est valide et prêt à fonctionner. Lorsqu’il vaut 0, le module n’est pas valide.

 

Rôle des bits du registre ADCON1

Voir aussi la documentation technique du microcontrôleur, pour la constitution interne de ce régistre.

Les bits 7 et  6 :  ne sont pas implémentés, et sont lus comme des 0 ;

Le bit 5 : ADFM : sélection du format du résultat de la conversion ;

Le bit 4 : n’est pas implémenté et est lu comme un 0 ;

Les bits 3 à 0 : PCFG3 à PCFG0 sont des bits de configuration des ports du CAN. Selon la valeur de ces bits, la broche du port se comporte soit comme une entrée analogique, soit comme une E/S numérique.

 

Une fois la configuration d’une entrée analogique réalisée, l’acquisition du canal désiré devra être faite avant d’effectuer la conversion. Chaque port d’entrée analogique devra aussi avoir son bit du registre TRIS positionné.

Pour résumer, voici quelques étapes nécessaires pour effectuer une conversion :

  1. La configuration du module du CAN (Configuration des entrées analogiques/de la tension de référence/des E/S numériques par ADCON1) ;
  2. La sélection des canaux d’entrée par ADCON0 ;
  3. Activation du module de conversion par ADCON0 ;
  4. Configuration de l’interruption CAN si possible ;
  5. Attente du temps de conversion ;
  6. Puis début de la conversion ;
  7. Attente la fin de la conversion.

 

L’afficheur à cristaux liquides (LCD) 2x16 caractères

Un grand nombre d'appareils électroniques ont des dispositifs de visualisation pour afficher du texte ou des valeurs de mesure. Ce rôle est confié souvent aux afficheurs LCD.

Le modèle que nous utilisons pour cet exemple possède 2 lignes de 16 caractères. Ce type d'afficheur possède 14 ou 16 broches selon les modèles.

afficheur lcd 2x16c a

 

Description des broches :

  • Broche 1 : GND, c’est la masse de l’alimentation (0 V).
  • Broche 2 : VDD, c’est l’alimentation du contrôleur interne (+5 V).
  • Broche 3 : VEE (ou VO), c’est l’alimentation du panneau à cristaux liquides, sert au réglage du contraste.
  • Broche 4 : RS ou Register Select, elle permet au contrôleur interne de l’afficheur LCD de faire la distinction entre une donnée et une instruction. Lorsque RS = 1, on a la sélection du registre de données. Lorsque RS = 0, en mode lecture, on a sélection du registre d’instruction ; et en mode écriture sélection du compteur d’adresse et du drapeau BUSY.
  • Broche 5 : R/W, elle permet de lire ou d’écrire. Lorsque R/W = 1, c'est une lecture. Lorsque R/W = 0 c'est une écriture.
  • Broche 6 : E ou Enable, c’est une entrée de validation.
  • Broches 7 à 14 : DB0 à DB7, constituent le bus de données, qui peut être configuré en entrée en mode écriture ; et en sortie en mode lecture.
  • Les deux autres broches restantes, à savoir les broches 15 et 16 (uniquement pour les afficheurs qui en sont équipés), servent pour l’anode et la cathode de la diode de rétro éclairage.

Cet afficheur est géré par un contrôleur interne. Il en existe différent types sur le marché ; tout dépend du fabriquant de l’afficheur. On a par exemple le HD44780 de HITACHI, ou le KS0070B de SAMSUNG, pour ne citer que ceux-là. Mais tous sont en général compatibles ; quelques petites différences peuvent subsister au niveau de la table des caractères.

Connexions du module LCD?

connexions lcd pic16f877a 1

Pour régler le contraste, le curseur du potentiomètre de 10KΩ est relié à V0. Avant la mise sous tension, il faudra veiller à ce que le curseur du potentiomètre soit positionné au milieu de la résistance, si non, on peut mettre en série une résistance de quelques Kilo Ohm avec le potentiomètre.

La résistance R2 reliée à l'anode sera de l'ordre de quelques dizaines d'ohm pour avoir un courant de 100 mA dans l'afficheur (voir doc du fabricant).

Instructions de contrôle et d’affichage 

Beaucoup de modules d'affichage LCD pour caractères ASCII font appel à des circuits contrôleurs ayant un fonctionnement identique. Ce type de contrôleur dispose de 11 instructions ; le tableau ci-après en donne une brève description :

On notera que  X aura pour valeur 0 ou 1, CGRAM = Characters Generator RAM, DDRAM = Display Data RAM. Type de contrôleur:HD44780U - Fréquence: 250 kHz

InstructionRSR/WDB7DB6DB5DB4DB3DB2DB1DB0DescriptionDurée
Display Clear 0 0 0 0 0 0 0 0 0 1 Efface l'écran et place le curseur à la position d'origine. (Adresse de DDRAM = 0) 62 µs - 1.64 ms
Return Home 0 0 0 0 0 0 0 0 1 X Place le curseur à la position d'origine. Le contenu de la DDRAM reste inchangé 1,64 ms
Entry Mode set 0 0 0 0 0 0 0 1 I/D S I/D=1: le curseur se déplace d'une position à droite
I/D=0: le curseur se déplace d'une position à gauche
S=1 : décalage de l'afficheur dans les de déplacement du curseur
S=0 : aucune action
40 µs
Display ON/OFF Control 0 0 0 0 0 0 1 D C B D=1 : affichage visible
D=0 : affichage invisible
C=1 : curseur visible
C=0 : curseur invisible
B=0: curseur clignote
B=1 :curseur fixe
40 µs
Cursor Display or Shift 0 0 0 0 0 1 S/C R/L X X S/C=1 : décalage de l'affichage
S/C=0: déplacement du curseur
R/L=1 : décalage à droite
R/L=0 : décalage à gauche
40 µs
Function set 0 0 0 0 1 DL N F X X DL=1: mode de fonctionnement 8 bits
DL=0: mode de fonctionnement 4 bits
N=1: deux lignes d'affichage
N=0: une ligne d'affichage
F=1 : matrice 5x11
F=0: matrice 5X8
40 µS
Set CGRAM Address 0 0 0 1 A5 A4 A3 A2 A1 A0 Positionne l'adresse de la CGRAM 40 µs
Set DDRAM Address 0 0 1 A6 A5 A4 A3 A2 A1 A0 Positionne le compteur d'adresse de la DDRAM 40 µs
Write Data to CGRAM or DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 Ecrit la donnée D7-D0 à l'adresse définie par l'instruction set CGRAM Address il en est de même pour la DDRAM 40 µs
Read Busy Flag and Address counter 0 1 BF AC6 AC5 AC4 AC3 AC2 AC1 AC0 Lit le drapeau busy flag et le compteur d'adresse. Lorsque BF=1 le contrôleur est occupé et n'accepte aucune nouvelle instruction
jusqu'à ce que BF passe à 1
0 µs
Read CGRAM or DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 Lit l'adresse de la CGRAM définie par Set CGRAM address il en est de même pour la DDRAM 40µs

 

Ce contrôleur est capable de gérer deux mode d’affichages: 5 x 7 points ou 5 x 10 points.

Avec en plus des caractères reservés au curseur.

 

DDRAM et CGROM :

Le contenu ou adresse de la DDRAM est lié à la position du caractère sur l’afficheur; par exemple pour un afficheur deux lignes:

afficheur lcd 2x16c p

Les adresses ci-dessus sont notées en haxadécimal.

La première position de la première ligne correspond à l’adresse DDRAM 0x00.

La sixième position de la deuxième ligne a pour adresse DDRAM 0x45.

Dans le cas d’un afficheur 2 lignes 16 caractères, les adresses DDRAM iront de 0x00 à 0x0F, pour la première ligne, et de 0x40 à 0x4F pour la seconde ligne. Les autres adresses sont ignorées.

La CGROM (Character Generator ROM) et la CGRAM (Character Generator RAM) sont deux mémoires contenant des caractères. La première contient des caractères prédéfinis et non modifiables, tandis que la seconde peut contenir des caractères personnalisables.

Pour le cas de la CGROM le constructeur donne un tableau de correspondance des caractères que l’afficheur peut fournir, en voici un extrait:

tableau caracteres lcd 2x16

 Il faut se référer à la documentation technique de l’afficheur pour avoir le tous les caractères qui peuvent être générés par cette mémoire, ainsi le code binaire correspondant.

Par exemple : supposons qu’on veut afficher le caractère E à la troisième position sur la première ligne, il faudra effectuer les instructions suivantes :

  • Set DDRAM Address (A6…A0) = 0x02, pour préciser la position;
  • Write Data to DDRAM (D7…D0) = 01000101 en binaire soit 0x45 en hexadécimal.

La CGRAM dispose de quelques caractères personnalisables; en tout 8 d’après la documentation du HD44780.

Un petit retour en arrière sur le schéma du montage qui sera réalisé, montre que l’afficheur est interfacé sur 4 bits.

L’envoi des données sur 4 bits est lent par rapport au mode de transfert sur 8 bits, car on doit s’y prendre par deux fois. Qu’importe ; on n’est pas tenu par une rapidité d’affichage extrême dans notre exemple.

Pour gagner une broche on a relié R/W à la masse, ainsi l’afficheur ne fonctionne qu’en écriture. Dans ce cas le drapeau BUSY ne sera plus disponible. Cette lacune sera compensée au niveau du programme par des temps d’attentes un peu plus long entre l’écriture de deux instructions.

Exemple de chronogramme pour un cycle d'écriture transfert extrait de la documentation technique Samsung:

signaux lcd 2

Ce chronogramme montre les durées minimale qu'il faudrait attendre pour un bon fonctionnement de l'afficheur. Par exemple pour un afficheur HD44780U:

tC : temps de cycle minimum pour E = 500ns;

tW : largeur minimale de l'impulsion E = 230ns;

tSU1 : minimum d'attente lorsque R/W passe à 0 et la génération de l'impulsion E = 40ns;

tSU2 : attente minimale de données pour être valide = 80ns

 

Pour clore cette partie, on trouve assez facilement ce type d’afficheur dans des grandes enseignes de la grande distribution comme RADIOSPARES ou FARNELL, GoTronic, et il y en a bien d'autres; sous forme de versions améliorées, certains sont pilotés par des interfaces séries comme l'interface I2C par exemple.

 

Programmation

Pour simplifier la tâche, nous allons scinder cette étape consacrée au logiciel en deux parties; de plus nous avons préféré écrire les commentaires en anglais pour décrire les programmes.

Dans un premier temps on va réaliser, tester et simuler un programme qui permettra de commander l’afficheur tout seul ; une fois ceci accompli, on pourra donc réaliser le programme du convertisseur avec son module d’affichage ; puis simuler le fonctionnement et programmer le microcontrôleur.

 

Commande de l’afficheur LCD

On commencera par créer un fichier d’entête pour l’afficheur LCD, nommé « lcd.h ». Ensuite ce fichier sera intégré dans un autre appelé « includes.h », qui contiendra toutes les librairies dont on aura besoin pour les fichiers sources.  Ainsi deux fichiers sources seront crées :  « lcd.c »  et « main.c ».

Le fichier « lcd.h »

/* 
 * File:   lcd.h
 * Author: Bidj
 * Comments:
 * Revision history: 29-06-2019
 */


// Function Declarations for Generic Functions.c

#ifndef __LCD
#define __LCD

// Define Pins
#define LCD_E    		RB1             // Enable pin for LCD RB1
#define LCD_RS	 		RB0             // RS pin for LCD RB0
#define LCD_Data_Bus_D4		RB4		// Data bus bit 4
#define LCD_Data_Bus_D5		RB5		// Data bus bit 5
#define LCD_Data_Bus_D6		RB6		// Data bus bit 6
#define LCD_Data_Bus_D7		RB7		// Data bus bit 7

// Define Pins direction registers
#define LCD_E_Dir     		TRISB1
#define LCD_RS_Dir   	 	TRISB0
#define LCD_Data_Bus_Dir_D4   	TRISB4
#define LCD_Data_Bus_Dir_D5     TRISB5
#define LCD_Data_Bus_Dir_D6  	TRISB6
#define LCD_Data_Bus_Dir_D7 	TRISB7

// Constants
#define E_Delay       50  


// Function Declarations
void WriteCommandToLCD(unsigned char);
void WriteDataToLCD(char);
void InitLCD(void);
void WriteStringToLCD(const char*);
void ClearLCDScreen(void);
void Set_LCD_Cursor(unsigned char,unsigned char);

#endif

 

Dans ce fichier on trouve, la définition et la configuration des ports du microcontrôleur qui servent pour la commande de l’afficheur, ainsi que les prototypes des fonctions utilisées par le programme « lcd.c ».

Le fichier « includes.h »

Contient tous les fichiers d’entêtes du programme. Dans l’extrait qui suit les fichiers d’entête du convertisseur ne sont pas encore ajoutés.

#ifndef __INCLUDES_H
#define __INCLUDES_H
#include "xc.h"
#include "lcd.h"
// Define CPU Frequency
// This must be defined, if __delay_ms() or 
// __delay_us() functions are used in the code
#define _XTAL_FREQ   20000000  
// configuration bits
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

//
#endif

Le programme « lcd.c »

Il effectue toutes les tâches de commande de l’afficheur, depuis l’initialisation jusqu’à l’écriture des caractères.

/*
 * File:   lcd.c
 * Author: bidj
 *
 * Created on 29 juin 2019, 16:18
 */
#include "Includes.h"


void ToggleEpinOfLCD(void)
{
	LCD_E = 1;                // Give a pulse on E pin
	__delay_us(E_Delay);      // so that LCD can latch the
	LCD_E = 0;                // data from data bus
	__delay_us(E_Delay); 	
}


void WriteCommandToLCD(unsigned char Command)  
{
	LCD_RS = 0;				  // It is a command
	
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= (Command&0xF0);  // Write Upper nibble of data
	ToggleEpinOfLCD();		  // Give pulse on E pin	
	
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= ((Command<<4)&0xF0); // Write Lower nibble of data 
	ToggleEpinOfLCD();		  // Give pulse on E pin
}


void WriteDataToLCD(char LCDChar)  
{
	LCD_RS = 1;				  // It is data
	
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= (LCDChar&0xF0);  // Write Upper nibble of data
	ToggleEpinOfLCD();		  // Give pulse on E pin	
	
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= ((LCDChar<<4)&0xF0); // Write Lower nibble of data
	ToggleEpinOfLCD();		  // Give pulse on E pin
}


void InitLCD(void)
{ 
	// Firstly make all pins output
	LCD_E  		         = 0;   // E  = 0
	LCD_RS  	 	 = 0;   // RS = 0
	LCD_Data_Bus_D4		 = 0;  	// Data bus = 0
	LCD_Data_Bus_D5		 = 0;  	// Data bus = 0
	LCD_Data_Bus_D6		 = 0;  	// Data bus = 0
	LCD_Data_Bus_D7		 = 0;  	// Data bus = 0
	LCD_E_Dir    		 = 0;   // Make Output
	LCD_RS_Dir    	 	 = 0;   // Make Output
	LCD_Data_Bus_Dir_D4  = 0;   // Make Output
	LCD_Data_Bus_Dir_D5  = 0;   // Make Output
	LCD_Data_Bus_Dir_D6  = 0;   // Make Output
	LCD_Data_Bus_Dir_D7  = 0;   // Make Output

  ///////////////// Reset process from datasheet //////////////
   __delay_ms(40);
   
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= 0x03;			  // Write 0x3 value on data bus
	ToggleEpinOfLCD();		  // Give pulse on E pin

   __delay_ms(10);
   
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= 0x03;			  // Write 0x3 value on data bus
	ToggleEpinOfLCD();		  // Give pulse on E pin

   __delay_us(20);
   
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= 0x03;			  // Write 0x3 value on data bus
	ToggleEpinOfLCD();		  // Give pulse on E pin

   __delay_ms(2);
   
	PORTB &= 0x0F;			  // Make Data pins zero
	PORTB |= 0x20;			  // Write 0x2 value on data bus
	ToggleEpinOfLCD();		  // Give pulse on E pin
	
	__delay_ms(20);
  /////////////// Reset Process End ////////////////
	WriteCommandToLCD(0x02);
	//WriteCommandToLCD(0x28);   //function set 28
        WriteCommandToLCD(0x08);
        WriteCommandToLCD(0x00); 
	WriteCommandToLCD(0x0C);    //display on,cursor off,blink off
        WriteCommandToLCD(0x00); 
	WriteCommandToLCD(0x06);    //entry mode, set increment
}


void WriteStringToLCD(const char *s)
{
	while(*s)
	WriteDataToLCD(*s++);   // print first character on LCD 
}


void ClearLCDScreen(void)       // Clear the Screen and return cursor to zero position
{
	WriteCommandToLCD(0x01);    // Clear the screen
	__delay_ms(2);              // Delay for cursor to return at zero position
}
//
void Set_LCD_Cursor(unsigned char a, unsigned char b)
{
	char temp; //,z,y;
	if(a == 1)
	{
	    temp = 0x80 + b - 1;
	    WriteCommandToLCD(temp); //Lcd_Cmd(y);
	}
	else if(a == 2)
	{
		temp = 0xC0 + b - 1;
		WriteCommandToLCD(temp); //Lcd_Cmd(y);
	}

}

 

Le programme « main.c »

Constitue le programme principal, on commence donc par initialiser l’afficheur, c'est-à-dire le mode de transfert (4 bits), l’état du curseur, puis on efface l’écran. 

L’afficheur est donc prêt à recevoir des caractères ; par exemple ici on va afficher la chaine caractères «Bienvenue!!».  Une fois affiché, on se fixe un délai d’attente de 1s avant de se mettre en position d’attente.

/*
 *
 * file: main.c                                                   
 *
 * Author: bidj – 27 Juin 2019                                     
 */

#include "Includes.h"

// Main Function

void main(void)

{

      InitLCD();        // Initialize the LCD
      WriteStringToLCD("Bienvenue!!"); // Write String

            __delay_ms(1000);            // Delay of 1 sec

      while(1)

      {

//

      }

}

 

Simulation 

Pour simuler le fonctionnement de ce programme à l’aide de Proteus, il faudra d’abord configurer MPLAB X afin qu’il puisse utiliser Proteus VSM Viewer (Voir Programmation du PIC16F877A - Partie 1).

En cliquant sur l’icône « Build », le projet s’ouvre et se met automatiquement en mode simulation. On obtiendra la figure ci-après :

affichage lcd pic16f877a 1

Conversion analogique numérique

La réalisation du programme est essentiellement basée sur l’initialisation de la voie de conversion, le calcul de la conversion, et l’affichage du résultat.

Pour cela les fichiers d’entêtes seront modifiés puisque seront rajoutés les définitions de ports et des fonctions associés au convertisseur analogique numérique. En rapport avec l’exemple traité plus haut.  Deux autres fichiers ont été ajoutés au projet:

Le fichier "adc.h":

/* 
 * File:   adc.h
 * Author: Bidj
 * Comments:
 * Revision history: 29-06-2019
 */

#ifndef __ADCFunctions_H
#define __ADCFunctions_H

//Define Channels
#define AN0  0
#define AN1  1
#define AN2  2
#define AN3  3
#define AN4  4
#define AN5  5
#define AN6  6
#define AN7  7

//Function Declarations
void InitADC(void);
unsigned int GetADCValue(unsigned char);

#endif

 

Le fichier « adc.c »  :

/*
 * File:   adc.c
 * This file is intended to get ADC Value
 * Author: bidj
 *
 * Created on 30 juin 2019, 11:20
 */

#include "Includes.h"

void InitADC(void)
{
	ADCON1  = 0x80;	     // Make PORTA and PORTE analog pins
						 // Also, Vref+ = 5v and Vref- = GND
	TRISA   = 0x2f;      // Make RA5, RA3, RA2, RA1, RA0 input
	TRISE   = 0x07;		 // Make RE0, RE1 and RE2 input
	ADCON0  = 0x81;		 // Turn on the A/D Converter
}


/*
 * Function Name: GetADCValue
 * Inputs :     Channel name, it can be AN0, AN1, AN2, AN3, AN4
 *                AN5, AN6 or AN7 only. Channel is selected according
 *                to the pin you want to use in the ADC conversion. 
 *                For example, use AN0 for RA0 pin. Similarly for 
 *                RA1 pin use AN1...
 * Outputs:     10 bit ADC value is read from the pin and returned.     
 */
unsigned int GetADCValue(unsigned char Channel)
{
	ADCON0 &= 0xc7;         // Clear Channel selection bits
	ADCON0 |= (Channel<<3); // Select channel pin as ADC input
    
    __delay_ms(10);         // For Acqusition Time 
							// to charge up and show correct value
	GO_nDONE  = 1;		    // Enable Go/Done

	while(GO_nDONE);        // Wait for conversion completion

	return ((ADRESH<<8)+ADRESL);   // Return 10 bit ADC value
}

 

Le fichier Includes.h a subit une légère modification en conséquence: les librairies "adc.h" crée pour le convertisseur analogique-numérique; ainsi la librairie standard "stdio.h" ont été ajoutées.

Le fichier main.c lui aussi a été modifié pour afficher le résultat de la conversion :

/*
 * File:   main.c
 * Author: bidj
 * Created on 29 juin 2019, 10:18
 */

#include "Includes.h"


// Main Function

void main(void)

{

      unsigned int ADC_value = 0;
      unsigned int digit1, digit2, digit3, digit4;
    // unsigned int ADC_value1 = 0;

  

      InitADC();              // Initialize ADC
      InitLCD();              // Initialize LCD

      while(1)

      {

            ClearLCDScreen(); // Clear LCD screen
            ADC_value = GetADCValue(AN7); // Read ADC value from RE2(AN7) pin
            ADC_value = (5.0/1024.0)*ADC_value; //
            sprintf(value,"U = %.3f",ADC_value);
            Set_LCD_Cursor(1, 1);
            WriteStringToLCD(value);
            WriteStringToLCD(" Volts");
            __delay_ms(500); // Half second delay before next reading

      }

}

 

 

Simulation

Dans l’environnement MPLAB X, si lance la simulation on obtient le résultat suivant :

affichage lcd pic16f877a 2

Réalisation

On dispose d’une plaque à essai, d’un potentiomètre ajustable multi tours de 470 k Ohm, d’un afficheur lcd 2 x 16 caractères, et d’un multimètre.

affichage lcd pic16f877a 3

Une mesure faite à l'aide du multimètre donne le résultat suivant:

affichage multimetre 1

Dans cet article on a mis en oeuvre le convertisseur analogique numérique du microcontrôleur PIC, à l'aide d'un potentiomètre; ce composant peut être remplacé par des capteur, afin de créer une mini-chaîne d'acquisition de données.

Ce site web utilise des cookies

Certains d’entre eux sont essentiels pour son fonctionnement et d’autres nous aident à améliorer l’expérience utilisateur (cookies traceurs). Vous pouvez décider vous-même si vous autorisez ou non ces cookies. Merci de noter que, si vous les rejetez, certaines fonctionnalités du site pourront être défaillantes.