Code pour le projet de robot autonome : Partie 2
Afin de vous simplifier le travail dans le cadre du projet robot, les éléments de code de taille importante à insérer au fur et à mesure du projet sont regroupés sur cette page. A noter qu’en cas d’incohérence avec le sujet, c’est celui-ci qui fait est juste a priori. Si c’est le cas, merci de me le signaler.
Pour formater proprement vos fichiers dans MPLABX, vous pouvez utiliser le raccourci de formatage automatique ALT+MAJ+F, après avoir au préalable sélectionné le texte à formater.
Liaison série en embarqué
#include <xc.h>
#include “UART.h”
#include “ChipConfig.h”
#define BAUDRATE 115200
#define BRGVAL ((FCY/BAUDRATE)/4)-1
void InitUART(void) {
U1MODEbits.STSEL = 0; // 1-stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-data bits
U1MODEbits.ABAUD = 0; // Auto-Baud Disabled
U1MODEbits.BRGH = 1; // Low Speed mode
U1BRG = BRGVAL; // BAUD Rate Setting
U1STAbits.UTXISEL0 = 0; // Interrupt after one Tx character is transmitted
U1STAbits.UTXISEL1 = 0;
IFS0bits.U1TXIF = 0; // clear TX interrupt flag
IEC0bits.U1TXIE = 0; // Disable UART Tx interrupt
U1STAbits.URXISEL = 0; // Interrupt after one RX character is received;
IFS0bits.U1RXIF = 0; // clear RX interrupt flag
IEC0bits.U1RXIE = 0; // Disable UART Rx interrupt
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART Tx
}
Interruption en mode loopback
//Interruption en mode loopback
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void) {
IFS0bits.U1RXIF = 0; // clear RX interrupt flag
/* check for receive errors */
if (U1STAbits.FERR == 1) {
U1STAbits.FERR = 0;
}
/* must clear the overrun error to keep uart receiving */
if (U1STAbits.OERR == 1) {
U1STAbits.OERR = 0;
}
/* get the data */
while (U1STAbits.URXDA == 1) {
U1TXREG = U1RXREG;
}
}
Buffer circulaire en émission
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include “CB_TX1.h”
#define CBTX1_BUFFER_SIZE 128
int cbTx1Head;
int cbTx1Tail;
unsigned char cbTx1Buffer[CBTX1_BUFFER_SIZE];
unsigned char isTransmitting = 0;
void SendMessage(unsigned char* message, int length)
{
unsigned char i=0;
if(CB_TX1_RemainingSize()>length)
{
//On peut écrire le message
for(i=0;i<length;i++)
CB_TX1_Add(message[i]);
if(!CB_TX1_IsTranmitting())
SendOne();
}
}
void CB_TX1_Add(unsigned char value)
{
…
}
unsigned char CB_TX1_Get(void)
{
…
}
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void) {
IFS0bits.U1TXIF = 0; // clear TX interrupt flag
if (cbTx1Tail!=cbTx1Head)
{
SendOne();
}
else
isTransmitting = 0;
}
void SendOne()
{
isTransmitting = 1;
unsigned char value=CB_TX1_Get();
U1TXREG = value; // Transmit one character
}
unsigned char CB_TX1_IsTranmitting(void)
{
…
}
int CB_TX1_RemainingSize(void)
{
int rSize;
..
return rSize;
}
Buffer circulaire en réception
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include “CB_RX1.h”
#define CBRX1_BUFFER_SIZE 128
int cbRx1Head;
int cbRx1Tail;
unsigned char cbRx1Buffer[CBRX1_BUFFER_SIZE];
void CB_RX1_Add(unsigned char value)
{
if(CB_RX1_GetRemainingSize()>0)
{
…
}
}
unsigned char CB_RX1_Get(void)
{
unsigned char value=cbRx1Buffer[cbRx1Tail];
…
return value;
}
unsigned char CB_RX1_IsDataAvailable(void)
{
if(cbRx1Head!=cbRx1Tail)
return 1;
else
return 0;
}
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void) {
IFS0bits.U1RXIF = 0; // clear RX interrupt flag
/* check for receive errors */
if (U1STAbits.FERR == 1) {
U1STAbits.FERR = 0;
}
/* must clear the overrun error to keep uart receiving */
if (U1STAbits.OERR == 1) {
U1STAbits.OERR = 0;
}
/* get the data */
while(U1STAbits.URXDA == 1) {
CB_RX1_Add(U1RXREG);
}
}
int CB_RX1_GetRemainingSize(void)
{
int rSizeRecep;
…
return rSizeRecep;
}
int CB_RX1_GetDataSize(void)
{
int rSizeRecep;
…
return rSizeRecep;
}
Décodage des messages en C#
public enum StateReception
{
Waiting,
FunctionMSB,
FunctionLSB,
PayloadLengthMSB,
PayloadLengthLSB,
Payload,
CheckSum
}
StateReception rcvState = StateReception.Waiting;
int msgDecodedFunction = 0;
int msgDecodedPayloadLength = 0;
byte[] msgDecodedPayload;
int msgDecodedPayloadIndex = 0;
private void DecodeMessage(byte c)
{
switch(rcvState)
{
case StateReception.Waiting:
…
break;
case StateReception.FunctionMSB:
…
break;
case StateReception.FunctionLSB:
…
break;
case StateReception.PayloadLengthMSB:
…
break;
case StateReception.PayloadLengthLSB:
…
break;
case StateReception.Payload:
…
break;
case StateReception.CheckSum:
…
if (calculatedChecksum == receivedChecksum)
{
//Success, on a un message valide
}
…
break;
default:
rcvState = StateReception.Waiting;
break;
}
}
Décodage des messages en embarqué
#include <xc.h>
#include “UART_Protocol.h”
unsigned char UartCalculateChecksum(int msgFunction,
int msgPayloadLength, unsigned char* msgPayload)
{
//Fonction prenant entrée la trame et sa longueur pour calculer le checksum
…
}
void UartEncodeAndSendMessage(int msgFunction,
int msgPayloadLength, unsigned char* msgPayload)
{
//Fonction d’encodage et d’envoi d’un message
…
}
int msgDecodedFunction = 0;
int msgDecodedPayloadLength = 0;
unsigned char msgDecodedPayload[128];
int msgDecodedPayloadIndex = 0;
void UartDecodeMessage(unsigned char c)
{
//Fonction prenant en entrée un octet et servant à reconstituer les trames
…
}
void UartProcessDecodedMessage(unsigned char function,
unsigned char payloadLength, unsigned char* payload)
{
//Fonction appelée après le décodage pour exécuter l’action
//correspondant au message reçu
…
}
//*************************************************************************/
//Fonctions correspondant aux messages
//*************************************************************************/