#include <pic.h> //obligatoire, de base
//Quartz 4Mhz
#define PIC_CLK 4000000
//Les routines de temporisation
#include "delay.h"
//J'utilise un quartz, mon code n'est pas protégé
__CONFIG(FOSC0|PWRTE |CP);
/**
* Gestion laison RS232 à 9600 bauds
*
*/
//Fonctions de manipulation des bits en remplacement des structures unions
et typedef
#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
#define getbit(data,bitno) ((data>>bitno)&0x01)
#define setnbit(data,bitno) (data<<bitno)
#define setbit(data,bitno,value) (data&(~setnbit(1,bitno))|setnbit(value,bitno))
#define togglebit(data) (data^0x01)
//temps en microseconde pendant lequel le microcontroleur est aveugle
à un changement d'état sur une de ses broches d'IT
#define TirqLatency 60
/************Liaison série *******************************/
//Paramètres de Reception
//-----------------------
#define Tbit_rx_RS232 104 //Reception T=1/9600=104us à 9600 bauds
#define Jump_over_RS232_rx_startbit (Tbit_rx_RS232-TirqLatency+(Tbit_rx_RS232/2))
#define Nb_RS232_rx_databits 8 // 8 bits de données
#define Jump_over_RS232_rx_databits (Tbit_rx_RS232-15) //la boucle d'éxécution
prends 12us
#define Nb_RS232_rx_stopBits 1 //1 bit stop
#define Jump_over_RS232_rx_stopbits (Nb_RS232_rx_stopBits*Tbit_rx_RS232)
//Paramètres d'envoi
//------------------
#define Tbit_tx_RS232 104
#define Duration_RS232_tx_startbit (Tbit_tx_RS232-30)
#define Nb_RS232_tx_databits 8
#define Duration_RS232_tx_databits (Tbit_tx_RS232-30) //la boucle d'xcution
prends 12us
#define Nb_RS232_tx_stopBits 1
#define Duration_RS232_tx_stopbits (Nb_RS232_tx_stopBits*Tbit_tx_RS232)
#define ITMask 0B10110000
//-----Attribution des broches -------------
static bit RS_OUT @ PORTBIT(PORTA, 4); //Borche d'envoi
static bit RS_IN @ PORTBIT(PORTB, 7); //Broche de reception
//Pour voir le caractère envoyé sur 8 leds
volatile bit D1 @ PORTBIT(PORTB, 3);
volatile bit D2 @ PORTBIT(PORTB, 2);
volatile bit D3 @ PORTBIT(PORTB, 1);
volatile bit D4 @ PORTBIT(PORTB, 0);
volatile bit D5 @ PORTBIT(PORTA, 3);
volatile bit D6 @ PORTBIT(PORTA, 2);
volatile bit D7 @ PORTBIT(PORTA, 1);
volatile bit D8 @ PORTBIT(PORTA, 0);
//---- Variables de travail ---------------------------
//variable utilisée par les routines de temporisation
volatile unsigned int timeout;
//variable tampon
unsigned char Buff;
unsigned char TxBuff; // caractère à emettre
unsigned char RxBuff;// caractère reçu
//------ Déclaration des routines RS232 -------------------------------
void RSsend(void); /* Send the char Buff on the serial port */
void RSget(void); /* Read the serial port and save it into Buff*/
//------- Déclaration des routines pour afficher sur les leds--------------
void WriteParport(void);
void ReadParport(void);
//------ Le programme principal intialise les ports et autorise les
interruptions ---------
main()
{
//Indique si les broches sont des entrées ou des sorties
TRISB = ITMask;
TRISA = 0;
//Fixe les valeurs des ports par défaut
PORTA = 0;
PORTB = 0b10000000; //Initialize RS_IN
RS_OUT=1;
//autorise les interruptions sur le port B
RBIE=1;
GIE=1;
//boucle infinie qui n'attend qu'à être interrompue
for(;;) {
}
}
//-----Affiche le contenu de Buff sur le port des 8 leds
void WriteParport(void) {
D1=getbit(Buff,0);
D2=getbit(Buff,1);
D3=getbit(Buff,2);
D4=getbit(Buff,3);
D5=getbit(Buff,4);
D6=getbit(Buff,5);
D7=getbit(Buff,6);
D8=getbit(Buff,7);
}
//----récupère la valeur de Buff en fonction de la valeur
sur les leds D1-D8
void ReadParport(void) {
Buff=setbit(Buff,0,D1);
Buff=setbit(Buff,1,D2);
Buff=setbit(Buff,2,D3);
Buff=setbit(Buff,3,D4);
Buff=setbit(Buff,4,D5);
Buff=setbit(Buff,5,D6);
Buff=setbit(Buff,6,D7);
Buff=setbit(Buff,7,D8);
}
unsigned char prev_portb=0B10000000; //mémorisation de la valeur
du port B
// Routine d'interruption déclenchée si un signal change
d'état sur une des broches prévues à cet effet:
// RB7, RB6,RB5,RB4 et RB0
interrupt isr()
{
//Détermine quelle broche du port B a changé d'état
et a généré cette interruption
if (RBIF)
{
RBIF=0; //on acquite l'interruption
if ((prev_portb ^ (PORTB&ITMask)) == 0B10000000)
{
//C'est la Broche RB7=RS IN qui a changé, un caractère
est à réceptionner
if ((PORTB & 0B10000000) == 0) //Si c'est le front descendant
du bit start alors
{
//On réceptionne le caractère
RSget();
//on l'affiche sur les leds
Buff=RxBuff;
WriteParport();
//et on fait un echo en envoyant à celui qui nous l'a envoyé
TxBuff=RxBuff;
RSsend();
}
}
prev_portb=PORTB&ITMask; //on prépare le port b au prochain
changement..
}
}
// RS232 routines
//------------------
/* Envoie sur la broche RA4 le caractère contenu dans TxBuff
au format RS232*/
void RSsend(void) {
unsigned b;
unsigned prevbit;
// Bit start
RS_OUT=0;
DelayUs(Duration_RS232_tx_startbit); //durée du motif start
//pour tous les bits de données..
for(b=Nb_RS232_tx_databits;b--;) {
prevbit=(TxBuff&0x01);
if(prevbit^RS_OUT) //si la valeur est différente du pécédent
bit
RS_OUT=TxBuff&0x01; //on l'envoie sinon on laisse la ligne comme est
l'est
if(b>0) //si ce n'est pas le premier bit de donnée, c'est qu'il
m'en reste encore à traiter
TxBuff=TxBuff>>1; //j'ai fini avec ce bit je le met à la
poubelle , au bit suivant
DelayUs(Duration_RS232_tx_databits);//durée d'un motif data
}
//Bit stop
RS_OUT=1;
DelayUs(Duration_RS232_tx_stopbits);//durée d'un motif stop
}
/* Recoit un caractère série sur RA1 et le stocke dans
RXBuff **/
void RSget(void) {
unsigned b;
RxBuff='\0';
//Saute par dessus le bit start et se positionne à la moitié
du premier bit de données
//RS_OUT=0;
DelayUs(Jump_over_RS232_rx_startbit); // la tempo qu'il faut
//RS_OUT=1;
//Lit consécutivement les 8 bits de données que l'on m'envoie
for(b=Nb_RS232_rx_databits;b--;) {
RxBuff=RxBuff | ((RS_IN&0x01)<<(Nb_RS232_rx_databits-1));
/* Pour déboguage */
//RS_OUT=0;
if(b>0) //reste il des bits à traiter?
RxBuff=RxBuff >> 1; //oui,alors au suivant
DelayUs(Jump_over_RS232_rx_databits); //on laisse passer la durée
d'un bit
//RS_OUT=1;
}
DelayUs(Jump_over_RS232_rx_stopbits); //facultatif car les bits stops
ne contiennent pas d'info
}
|