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