This tutorial give an example of using a I2C device on the MB1225 evaluation
kit. The device is a 0.56” 4-Digit 7-Segments Display w/I2C Backpack from Adafruit.
- A STMicroelectronics discovery kit with STM32F769NI MCU, order code 32F769IDISCOVERY (name on PCB: STM32F769I-DISCO).
- USB 2.0 male to micro USB cable (supplied with evaluation kit).
- A full installation of an Hyperpanel OS release on a linux based PC including tools for flashing and debugging. This tutorial requires release V10.03.02 for MB997D or higher. Hyperpanel OS releases are available for free in the Download section of the website.
- A Lunix PC with ARM gcc compiler, ARM gdb debugger and minicom installed.
- A text editor to edit or modify source codes (We are using vi in our demo).
- The 0.56″ 4-Digit 7-Segment Display with I2C Backpack from Adafruit.
Hyperpanel OS V30.01.01 for MB1225 (hypv300101.zip) or higher, available in the Download section.
Binary file
– On www.tutorial.hyperpanel.com, select Download from the main menu.
– Download “Hyperpanel OS V30.01.01 for MB1225” or higher release for the MB1225 kit (hypv300101.zip).
– On your PC Linux, copy and unzip the zip file in your root directory, for example:
cp hypv300101.zip /home/hyperpanel cd /home/hyperpanel unzip hypv300101.zip
– With a text editor, update hhome environment variable in the stm32m7 file:
cd ~/hypv300101/shells vi stm32m4
Update the first line, according to your root directory:
export hhome=/home/hyperpanel/hypv300101
– Save this file and an execute the command:
source stm32m7
– From this tutorial, use the button “Binary file” to download the zip file containing the binary. Unzip this file:
unzip hpos-tuto411-bin.zip
– Copy this binary file in HyperPanelOS release:
cp led7seg.bin ~/hypv300101/boards/stm32m7/exe
– Connect the 7-Segments LED screen to the MB1225 (see image). The Arduino Uno Rev3 Connector CN9 is ready to use as followed:
7-SEGMENTS LED MB1225-CN9 SIGNAL WIRE
SCL <-----------------> CN9/10/PB8/D15 I2C_SCL Yellow
SDA <-----------------> CN9/ 9/PB9/D15 I2C_SDA Green
VCC <-----------------> CN9/ 8/AVDD/AVDD Power Red
GND <-----------------> CN9/ 7/GND/GND Ground Black
– Connect the MB1225 board to a USB port on your Linux PC using the USB cable supplied with the board. Wait for a window to appear, then close it.
– Open a Terminal window and run minicom to get access to the Hyperpanel OS serial port and to the application messages:
minicom -D /dev/ttyACM0 -b 115200
– Open another Terminal window on your computer and enter the following commands:
cd ~/hypv300101/shells source stm32m7 exe
– Upload software to the board:
hgdb romload stm32m7 led7seg
You should see messages similar to these:
Open On-Chip Debugger 0.10.0+dev-00001-g0ecee83-dirty (2017-02-10-06:53) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html 0x08005634 in ?? () target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x20000046 msp: 0x20002000 auto erase enabled target halted due to breakpoint, current mode: Thread xPSR: 0x61000000 pc: 0x20000046 msp: 0x10002000 wrote 524288 bytes from file led7seg.bin in 10.224703s (50.075 KiB/s)
Cannot access memory at address 0xffffffff
led7seg.elf: No such file or directory.
Wait until the flashing operation is complete (approx. 30 seconds). The last message (led7seg.elf: No such file or directory) is normal.
– You can now press on the reset button (black button) of the MB1225. Hyperpanel OS will start, a counter “xx:xx” starts on the LED device and also on the serial port.
To go further
If you want to edit the source code, write modifications, compile, link, etc., here’s how to do it :
- From this tutorial, use the button “Source code” to download the zip file containing the source file. Unzip this file:
unzip hpos-tuto411-source.zip
- Copy this source code in HyperPanelOS release:
cp led7seg.c ~/hypv300101/user/stm32app
- Copy the link file in Hyperpanel release:
cp led7seg.lst ~/hypv300101/boards/stm32m7/exe
- You can edit and make any modifications you want in the source file. For example, you can modify the default “curtime” value. To do this, simply modify the value in the “loop_app_tsk()” procedure at the line 151 of the source file.
cd ~/hypv100302/user/stm32app vi led7seg.c
- Save the source file.
- Compile the source file:
cd ~/hypv100302/user/stm32app cmm led7seg
- Make a link edit to create a new executable:
exe lhypos led7seg
- You can now upload this new binary to the board, in the same way as in
the previous Installation chapter.
- The app gives an “how to use” example of an I2C device in “write” mode. The I2C driver available with HyperPanel OS support several controller/buses in parallel. In the case of the MB1225, there are several I2C bus but we use in the example one bus only.
- The 7-Segment Backpack Kit include one single I2C device. There are 4 digits and a double dot characters. Each digit have 7 segments and all segments have easy access thrue I2C messages.
- The I2C driver support IO lists, including waits, conditionnal jumps and intricated loops. We use here some “waits” command for initialization sequence, according to the information of datasheets.
- The driver provides two software interfaces in order to allow for both ease of use and versatility: Blocking and non blocking interfaces. We use here the blocking interface (i2c_write()).
- This example is a simple use of the bargraph with one device. But because I2C is a bus, we can connect several I2C devices and use them in the app (cf. other tutorials with several I2C devices).
Documents
Links
LED 7-segments animation
hypos-tuto411-source
/* ** led7seg.c - Sample code for HyperpanelOS ============================== ** ** ** ** This simple code is located into the application container, it is run ** ** by the VMK sub-operating system. On the other hand, the I/O container ** ** runs all the drivers that are VMIO finite state machines. ** ** ** ** The goal of this small app is to use a LED 7-segments I2C display device ** ** ** ** ======================================================================= ** */ /* Documentation for I2C devices -------------------------------------------- - HT16K33 18*8 LED Controller data sheet */ /* Include files and external reference -------------------------------------*/ #include <hypos.h> // Hyperpanel OS basic interfaces. */ #include <drv_asy.h> // Prototype of "asy_write()". */ #include <drv_i2c.h> // Prototype of "i2c_*()". */ /* Internal defines of this module ------------------------------------------*/ #define TICK 1000 // Code for tick event. #define DUMMY_AD 0xFF // I2C dev address - Dummy for wait. #define LED_AD 0xE0 // I2C dev address - LED (8bits address) #define INIT 0 // I2C command - Bargraph initialisation #define DOT_OFF 2 // I2C command - Double dot OFF #define DOT_ON 4 // I2C command - Double dot ON /* Internal global variables of this module --------------------------------*/ static unsigned int idto ; // Timer identifier. /* INIT command .............................................................*/ static const char init[] = // I2C command - Display initialisation { /* Length-1, Address, Control byte, Data byte */ 1, LED_AD , 0x21 , // BAR dev : Turn on oscillator 1, LED_AD , 0x81 , // BAR dev : Display ON Blinking OFF // BAR dev - Clear the display. 11, LED_AD , 0x00, 0x00, 0x00, // Character 1 0x00, 0x00, // Character 2 0x00, 0x00, // Double dot in the middle 0x00, 0x00, // Character 3 0x00, 0x00, // Character 4 0 , // End of command set } ; // static const char dot_off[] = // I2C command - Double dot OFF { /* Length-1, Address, Control byte, Data byte */ 2, LED_AD , 0x04, 0x00 , // Double dot OFF 1, DUMMY_AD , 50 , // Temporisation 0 , // End of command set } ; // static const char dot_on[] = // I2C command - Double dot ON { /* Length-1, Address, Control byte, Data byte */ 2, LED_AD , 0x04, 0x02 , // Double dot ON 0 , // End of command set } ; // static char *command[] = // I2C commands table { // (char*)&init , // I2C command - SCREEN_INIT (char*)0 , // Padding (char*)&dot_off , // I2C command - SET_LINE1 (char*)0 , // Padding (char*)&dot_on , // I2C command - SET_LINE2 (char*)0 , // Padding } ; // static const char digit[] = // Digit on 7-segment coding { 0x3F , // "0" digit 0x06 , // "1" digit 0x5B , // "2" digit 0x4F , // "3" digit 0x66 , // "4" digit 0x6D , // "5" digit 0x7D , // "6" digit 0x07 , // "7" digit 0x7F , // "8" digit 0x6F , // "9" digit } ; /* Prototypes --------------------------------------------------------------*/ static int loop_app_task(void*) ; // Prototype static int wait_evt(void) ; // Prototype static void set_command(int) ; // Prototype /* Beginning of the code --------------------------------------------------- loop_app_tsk Application entry point */ /* Procedure loop_app_tsk -------------------------------------------------- Purpose : This is our task main loop. */ int loop_app_tsk (void *param) { int ev = TICK ; // Our event int curtime = -1 ; // Current time in second int ret = 0 ; // Return procedure code char mess[32] ; // Message to be sent on ASY0 unsigned int time ; // Time to be display on 7-segments unsigned char buf[20] ; // /* Step 1 - Start a timer that will send an event every second ..............*/ set_uto(CLOCK , // Timer mode: clock 1000 , // Duration in milliseconds TICK , 0 , // Event code and reserve field &idto ); // Timer identifier /* Step 2 - LED 7-segment initialisation ....................................*/ asy_write(0,(unsigned char*)"Init ...\r\n",10); set_command(INIT) ; // LED 7-segment display initialization asy_write(0,(unsigned char*)"done\r\n",6); /* Step 3 - Get time ........................................................*/ curtime = 0 ; // Start at "00:00" /* Step 4 - Main loop .......................................................*/ wait_ev : // Beginning of loop label if ( ev == TICK ) // If the event is the tick event { // curtime ++ ; // Time incrementation /* Step 4.1 - Display time on serial port each second .......................*/ hsprintf(mess , // Format de timer message. " %02d:%02d\r\n" , // (curtime / 60)%60 , // Minutes. curtime %60 ); // Seconds. asy_write(0 , // Write on ASY0 (unsigned char*)mess , // the "mess" message strlen(mess) ); // Count of bytes to be sent /* Step 4.2 - Display timer on the LED 7-segments display each second .......*/ set_command(DOT_OFF) ; // Turn double dot OFF time=((curtime/60)%60)*100 + // Minutes. curtime %60 ; // Seconds. memset(buf , 0x00 , 15); // Reset display buffer memset(buf , 11 , 1); // Number of byte to write memset(buf+1 , LED_AD, 1); // I2C device address memset(buf+3 ,digit[(time/1000)%10],1); // Digit 1 memset(buf+5 ,digit[(time/ 100)%10],1); // Digit 2 memset(buf+9 ,digit[(time/ 10)%10],1); // Digit 3 memset(buf+11,digit[ time%10 ],1); // Digit 4 ret = i2c_write( // Send I2C command 0 , // Controller number PRO_I2C_DEV , // Protocol code -1 , // Target address unused with FLG_MULTI 0 , // Target sub-address buf , // Command 0 , // Count of bytes unused with FLG_MULTI FLG_MULTI ); // List of option flags if (ret) // i2c_write() return an error { // hsprintf(mess, // Format an error message "ERR <i2c_write> ret=%d",ret); // asy_write(0 , // Write message on ASY0 (unsigned char*)mess , // strlen(mess) ); // } // set_command(DOT_ON) ; // Turn double dot ON } ev = wait_evt() ; // Unschedule until an event is received goto wait_ev ; // Wait for the next event return 0 ; // Return code of the procedure } /* Procedure wait_evt ------------------------------------------------------*/ /* Purpose : Unschedule until the next event is received, whatever it is. */ static int wait_evt (void) { unsigned int waitlist[1][3] ; // Parameter of "waitevt_task" /***************************************************************************** * Step 1 : Build a list with one WAIT_CODEINT entry that will accept all * * ------ the event codes ranging from 0 to 20000. Then call * * "waitevt_task", we will be unscheduled until the next event will * * be received * *****************************************************************************/ waitlist[0][0] = WAIT_CODEINT ; // All events with waitlist[0][1] = 0 ; // a code between 0 waitlist[0][2] = 20000 ; // and 20000 waitevt_task(waitlist , // Address of waiting list 1 , // Size of "waitlist[]" 0 , // maximum waiting time = no 0 ) ; // Do not purge previous events /***************************************************************************** * Step 2 : Here we are scheduled again. The VMK has written into its * * ------ global variable "task_evt" a copy of the event that has * * scheduled us again. * *****************************************************************************/ return task_evt.code ; // Return event code } /* Procedure set_command ---------------------------------------------------*/ /* Purpose : Send a set of commands to I2C devices. */ static void set_command(int cmd) { int ret = 0 ; // Return procedure code char mess[64] ; // Message to be sent on ASY0 ret = i2c_write( // Send I2C command 0 , // Controller number PRO_I2C_DEV , // Protocol code -1 , // Target address unused with FLG_MULTI 0 , // Target sub-address (unsigned char*)command[cmd] , // Commands 0 , // Count of bytes unused with FLG_MULTI FLG_MULTI ); // Flag for "several cmd in same buffer" if (ret) // i2c_write() return an error { // hsprintf(mess, // Format an error message "ERR <i2c_write> ret=%d",ret); // asy_write(0 , // Write message on ASY0 (unsigned char*)mess , // strlen(mess) ); // } // }
Terminal
~/hypv100302/boards/stm32m7/exe >> hgdb GNU gdb (7.10-1ubuntu3+9) 7.10 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". man Display again this manual stm32m7 Send the reset halt command to openocd armdisconnect Deconnexion command peek adr Read and display a 32 bit value at adr poke adr val Write a val 32 bits value at adr poke_m adr msk val Write bits in a 32 bits word with a mask peekrange base o1 o2 Read 32 bits words from base+o1 to base+o2 affichb adr size Print a memory area starting at adr vmio n Display the tnote_evt_s debug table int Display the tnote_it debug table rte Return from interrupt romload stm32m7 app Write the app executable file in flash rom stm32m7 app Connect to target and load app dbg symbols gpio bank n state Set GPIO n (0-15) of bank (1-9) to 0/1 clock 0/1/2/3 Output SYSCLK/PLLI2S/HSE/PLL to MO2/PC9 (gdb) romload stm32m7 led7seg Open On-Chip Debugger 0.10.0+dev-00001-g0ecee83-dirty (2017-02-10-06:53) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html 0x00002ed2 in ?? () target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00003148 msp: 0x10002000 auto erase enabled target halted due to breakpoint, current mode: Thread xPSR: 0x61000000 pc: 0x20000046 msp: 0x10002000 wrote 393216 bytes from file led7seg.bin in 11.088839s (34.629 KiB/s) (gdb)