mardi 19 février 2013

Afficheur Alphanumérique (partie 3)



On va maintenant s’intéresser à l'interfaçage de la carte micro-contrôleur avec la raspberry pi.




Activation et vérification de l'I²C


Lors du démarrage de la raspberry pi, il est important que le driver I²C soit chargé

[   15.669863] Freeing init memory: 132K
[   15.891808] EXT4-fs (mmcblk0p2): re-mounted. Opts: user_xattr,acl,barrier=1,data=ordered
[   16.350619] udevd[59]: starting version 182
[   16.655836] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79)
[   16.748663] bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)
[   16.816541] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79)
[   18.934210] smsc95xx 1-1.1:1.0: eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
[   22.859421] NET: Registered protocol family 10
[   31.422506] Console: switching to colour dummy device 80x30
[   31.536753] bcm2708_fb_check_var info(c78b5000) 720x480 (720x480), 691200, 16
[   31.536774] bcm2708_fb_check_var var(c68ebdc8) 1x1 (1x1), 16, 345600
[   31.536792] bcm2708_fb_set_par info(c78b5000) 1x1 (1x1), 691200, 16
[   31.553110] BCM2708FB: start = c8826000,49385000 width=1, height=1, bpp=16, pitch=32 size=512 success=0
[   32.899219] eth0: no IPv6 routers present

Il faut chargé le driver i2c-dev.ko pour créer les noeuds /dev/i2c-0 et /dev/i2c-1

# modprobe i2c-dev
# lsmod
Module                  Size  Used by
i2c_dev                 4657  0
ipv6                  237083  14
spidev                  4274  0
spi_bcm2708             3969  0
i2c_bcm2708             3019  0

Pour vérifier si le microcontrôleur est bien connecté au bus I²C, on va utiliser l'utilitaire i2cdetect qui va nous donner tous les esclaves connectés à la raspberry pi.

# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

On remarque que l'esclave avec l'adresse 0x76 (le micro-contrôleur PIC16F876A) est bien vu par la raspberry pi.

Programme de test


Voici un petit programme de test sur la raspberry pi pour valider la communication I²C, elle permet d'afficher l'heure et la date du système :

Le fichier source :
/**
 * Objet    : 
 * --------------------------------------------------------------------------------
 * Fichier      : test_raspberry_lcd.c
 * --------------------------------------------------------------------------------
 * Version      : 0.1
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <pthread.h>

#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

/***********************************/
/* Includes des fichiers du projet */
/***********************************/

/**********************************/
/* Constantes internes au fichier */
/**********************************/

#define syslog_info(format, ...) syslog(LOG_INFO, format, ##__VA_ARGS__)
#define syslog_debug(format, ...) syslog(LOG_DEBUG, format, ##__VA_ARGS__)
#define syslog_err(format, ...) syslog(LOG_ERR, format, ##__VA_ARGS__)
#define syslog_warning(format, ...) syslog(LOG_WARNING, format, ##__VA_ARGS__)

/**********************************/
/* Structures internes au fichier */
/**********************************/
typedef char                            char_t;
typedef float                           float32_t;
typedef double                          float64_t;
typedef signed char                     int8_t;
typedef short int                       int16_t;
typedef int                             int32_t;
typedef unsigned char                   uint8_t;
typedef unsigned short int              uint16_t;
typedef unsigned int                    uint32_t;


int32_t main(int32_t __attribute__((unused)) argc, 
             char_t __attribute__((unused)) *argv[]) {
        int32_t i32_ret = -1;
        int32_t i32_fd_i2c = -1;
        char_t pi8_buf[16];
        
        int i32_adapter_nr = 0; /* probably dynamically determined */
        int i32_addr = 0x76; /* The I2C address */
        char_t sz_filename[20];
    
        // initialise buffer
        memset(pi8_buf, 0, sizeof(pi8_buf));
        memset(sz_filename, 0, sizeof(sz_filename));
    
        sprintf(sz_filename, "/dev/i2c-%d", i32_adapter_nr);
        
        // openlog is not necessary

        syslog_info("[TEST_RASPBERRY_I2C] Start process ...");

        // Open i2c dev node
        i32_fd_i2c = open(sz_filename, O_RDWR);
        if(i32_fd_i2c == -1) {
                syslog_err("[TEST_RASPBERRY_I2C] open : %m");
                return -1;
        }
        /* else nothing to do */

        i32_ret = ioctl(i32_fd_i2c, I2C_SLAVE, i32_addr);
        if (i32_ret == -1) {
                syslog_err("[TEST_RASPBERRY_I2C] ioctl : %m");
                return -1;
        }
        /* else nothing to do */

        // Clear display
        pi8_buf[0] = 0x01;
        pi8_buf[1] = 0x02;
        
        // write I²C frame
        i32_ret = write(i32_fd_i2c, pi8_buf, 2);
        if(i32_ret == -1) {
                syslog_err("[TEST_RASPBERRY_I2C] write : %m");
                close(i32_fd_i2c);
                return -1;
        }
        /* else nothing to do */
        
        sleep(1);

        while(1) {
                memset(pi8_buf, 0, sizeof(pi8_buf));
                
                // Return Home
                pi8_buf[0] = 0x02;
                pi8_buf[1] = 0x02;
                
                // write I²C frame
                i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
                if(i32_ret == -1) {
                        syslog_err("[TEST_RASPBERRY_I2C] write : %m");
                        close(i32_fd_i2c);
                        return -1;
                }
                /* else nothing to do */
                
                usleep(50000);
                
                st_time = time(NULL);
                pst_dateheure = localtime(&st_time);
                
                memset(pi8_buf, 0, sizeof(pi8_buf));
                pi8_line1_ptr = &pi8_buf[0];
                // String hour
                *pi8_line1_ptr = 0x05;
                pi8_line1_ptr ++;
                *pi8_line1_ptr = 14;
                pi8_line1_ptr ++;
                sprintf(pi8_line1_ptr, "    %02d:%02d:%02d", pst_dateheure->tm_hour, pst_dateheure->tm_min, pst_dateheure->tm_sec);
                
                // write I²C frame
                i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
                if(i32_ret == -1) {
                        syslog_err("[TEST_RASPBERRY_I2C] write : %m");
                        close(i32_fd_i2c);
                        return -1;
                }
                /* else nothing to do */
                
                usleep(100000);
                
                memset(pi8_buf, 0, sizeof(pi8_buf));
                
                // go to line 2, column 1
                pi8_buf[0] = 0x03;
                pi8_buf[1] = 0x04;
                pi8_buf[2] = 2;
                pi8_buf[3] = 1;
                
                // write I²C frame
                i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
                if(i32_ret == -1) {
                        syslog_err("[TEST_RASPBERRY_I2C] write : %m");
                        close(i32_fd_i2c);
                        return -1;
                }
                /* else nothing to do */
                
                usleep(50000);
                
                memset(pi8_buf, 0, sizeof(pi8_buf));
                pi8_line1_ptr = &pi8_buf[0];
                // String date
                *pi8_line1_ptr = 0x05;
                pi8_line1_ptr ++;
                *pi8_line1_ptr = 15;
                pi8_line1_ptr ++;
                sprintf(pi8_line1_ptr, "   %02d/%02d/%04d", pst_dateheure->tm_mday, (pst_dateheure->tm_mon + 1), (pst_dateheure->tm_year + 1900));

                // write I²C frame
                i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
                if(i32_ret == -1) {
                        syslog_err("[TEST_RASPBERRY_I2C] write : %m");
                        close(i32_fd_i2c);
                        return -1;
                }
                /* else nothing to do */
                
                usleep(50000);
        }
        
        // Close i2c dev node
        i32_ret = close(i32_fd_i2c);
        if(i32_ret == -1) {
                syslog_err("[TEST_RASPBERRY_I2C] close : %m");
                return -1;
        }
        /* else nothing to do */

        return 0;
}

Et le makefile :
CC = arm-unknown-linux-gnueabi-gcc
CFLAGS = -I../buildroot_test_a_del/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/include -W -Wall
LDFLAGS = -L../buildroot_test_a_del/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/lib -pthread -lrt 
EXEC = test_raspberry_lcd
OBJS = test_raspberry_lcd.o

all: $(EXEC)

$(EXEC):$(OBJS)
        @$(CC) -o $(EXEC) $^ $(LDFLAGS)

%.o:%.c
        @echo [CC] $^
        @$(CC) -o $@ -c $^ $(CFLAGS)

clean:
        @echo [CLEAN]
        @rm *.o $(EXEC) -f

On lance la compilation du programme de test avec la commande make et on vérifie que l’exécutable est bien compilé pour notre cible (raspberry pi).
# file test_raspberry_lcd
test_raspberry_lcd: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.2.25, not stripped

On lance l’exécutable de test avec la commande :
# ./test_raspberry_lcd

Résultat



Quelques photos









Lien vers la première partie du tutoriel : Afficheur alphanumérique (Partie 1)
Lien vers la deuxième partie du tutoriel : Afficheur alphanumérique (Partie 2)


Aucun commentaire:

Enregistrer un commentaire