//-----------------------------------------------------------------------------
// Mise en oeuvre de l'ecran LCD du Nokia 3310
// transmission par SPI, debug sur UART1 MAX3233E
// dsPIC 30F3010
// L. BAGHLI 10/03/2007 int Timer1 100 us
//-----------------------------------------------------------------------------
#include "p30F3010.h"
#include "lcd3310.h" // routines d'écriture sur l'ecran LCD et pilotage HP par PWM
//Configuration bits
/// Q=10 MHz
_FOSC(CSW_FSCM_OFF & XT_PLL8); //10Mhz *8 = 80 MHz /4 = 20 MIPS maxi pour ce pic
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & BORV_27 & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
#define FCY 20000000 //Instruction cycle rate (Osc x PLL / 4) = 20 MIPS
//#define T1Period 2000 // pour 100us à 20 MHz = T1Period = 2000=FCY*100us
#define T1Period 4000 // pour 200us à 20 MHz = T1Period = 4000=FCY*200us
//#define tcntPRD 5000 // combien de fois pour ariver en Te=1s avec des pas de 200us : 5000
#define tcntPRD 500 // combien de fois pour ariver en Te=0.1s avec des pas de 200us : 500
// Conversion Time MAX6675 norm 0.17s max 0.22 s
//#define tcntPRD 1250 // combien de fois pour ariver en Te=0.25s avec des pas de 200us : 2
#define MILLISEC FCY/20000 // 1 mSec delay constant
void setup_ports(void);
void DelayNmSec(unsigned int N);
void InitVar();
void InitUART();
void initTimer();
char Phrase[]="Lotfi is here";
char LCDbuffer[100];
char LCDbufferTmp[]="xx#xx#xx";
struct {
unsigned Running : 1;
unsigned CheckRX : 1;
unsigned SendTX : 1;
unsigned SendData : 1;
unsigned unused : 12;
} Flags;
unsigned int tcnt, TimeStamp;;
unsigned int Hour, Min, Sec;
// RS232 -------------------------------------------
unsigned char *TXPtr;
unsigned char *RXPtr;
void InitUART(void);
void SendMsg(void);
#define CR 0x0D
#define LF 0x0A
#define BAUD 19200
#define OffsetTimeStamp 10 // offset in OutData : position de la val de TimeStamp
unsigned char InData[] = {"000000"};
unsigned char OutData[] = {"TimeStamp=0000 Ssr0_T=0000\r\n"};
int SeqComm; // ttes les 0.5 s
#define SeqCommMax 5000
//-----------------------------------------------------------------------------
// Initialise variables
//-----------------------------------------------------------------------------
void InitVar(void)
{
tcnt=0; TimeStamp=0;
}
//-----------------------------------------------------------------------------
// Setup ports
//-----------------------------------------------------------------------------
void setup_ports(void)
{
// Clear All Ports Prior to defining I/O
PORTB=0; //Initialize LED pin data to off state
PORTC=0;
PORTD=0;
PORTE=0;
// Now set pin direction registers
TRISB = 0xFFFC; // RB0 interruptLED, LCD3310_RST / RB1 output, RB2-4 NC inputs 1111|1100
TRISC = 0xDFFF; // U1ATX/RC13 in , U1ATX/RC14 out , inutile pour le UART donc 0xFFFF is also ok
TRISD = 0xFFFC; // LCD3310_CS / RD0 out, LCD3310_DC / RD1 out
TRISE = 0x0000; // RE0-RE5 : out, RE5 PWM LCD3310_Speaker
LCD3310_RST=1; // pas de RST LCD
LCD3310_CS = 1; // Set SPI CS pin du LCD 3310 non actif
LCD3310_DC = 0; // Enter Data Mode
TRISF = 0xFFFB; // SDI1/RF2 in, SDO1/RF3 out 1011, inutile pour le SPI donc 0xFFFF is ok
}
//-----------------------------------------------------------------------------
// intitialise timer 1 et l interruption
//-----------------------------------------------------------------------------
void initTimer(void)
{
// Timer1 pour l ISR des 100 us
T1CON = 0; // ensure Timer 1 is in reset state, internal timer clock Fosc/4, no prescale
TMR1 = 0; // RAZ Timer1
IFS0bits.T1IF = 0; // reset Timer 1 interrupt flag
IPC0bits.T1IP = 4; // set Timer1 interrupt priority level to 4
IEC0bits.T1IE = 1; // enable Timer 1 interrupt
PR1 = T1Period; // set Timer 1 period register
T1CONbits.TON = 1; // enable Timer 1 and start the count
}
//---------------------------------------------------------------------
// Below are the interrupt vectors for the serial receive and transmit
//---------------------------------------------------------------------
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
IFS0bits.U1TXIF = 0; // clear interrupt flag
}
//---------------------------------------------------------------------
void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; // clear interrupt flag
*RXPtr = U1RXREG;
if (*RXPtr == CR)
{Flags.CheckRX = 1;
RXPtr = &InData[0];}
else *RXPtr++;
}
//------------------------------------------------------------------------
// Transmission over serial
void InitUART(void)
{
// Initialize the UART1 for BAUD = 19,200
U1MODE = 0x8400; // enable + alternate pins
// U1MODE = 0x8000; // enable + normal pins
U1STA = 0x0000;
U1BRG = ((FCY/16)/BAUD) - 1; // set baud to 19200
IEC0bits.U1RXIE = 1; // enable RX interrupt
RXPtr = &InData[0]; // point to first char in receive buffer
Flags.CheckRX = 0; // clear rx and tx flags
Flags.SendTX = 0;
Flags.SendData = 0; // clear flag
SeqComm=SeqCommMax;
U1STAbits.UTXEN = 1; // Initiate transmission
}
//----------------------------------------------------
// Convertit un "Word" hexa en "4 chars Hexadécimaux"
// et les sort sur la table en memoire
//----------------------------------------------------
inline void ConvHexa(int Var, int tablePos, unsigned char * table)
{
int tmp;
tmp=Var & 0x000F;
if (tmp<=9) tmp+=0x30;
else tmp+=0x37;
table[tablePos+3]=tmp;
tmp=Var>>4 & 0x000F;
if (tmp<=9) tmp+=0x30;
else tmp+=0x37;
table[tablePos+2]=tmp;
tmp=Var>>8 & 0x000F;
if (tmp<=9) tmp+=0x30;
else tmp+=0x37;
table[tablePos+1]=tmp;
tmp=Var>>12 & 0x000F;
if (tmp<=9) tmp+=0x30;
else tmp+=0x37;
table[tablePos]=tmp;
}
//----------------------------------------------------
// Convertit un "12 bits" en "4 chars décimaux. 2 chars" xxxx.xx
// maximum : 1023.75 pour 12 bits
// et les sort sur la table en memoire
//----------------------------------------------------
inline void ConvDec(int Var, int tablePos, unsigned char * table)
{
unsigned int k;
unsigned char c;
// Char
k = Var>>2;
c = k/1000;
if (c > 0)
k = k - c*1000;
table[tablePos] =(c + 0x30);
c = k/100;
if (c > 0)
k = k - c*100;
table[tablePos+1]=(c + 0x30);
c = k/10;
if (c > 0)
k = k - c*10;
table[tablePos+2]=(c + 0x30);
table[tablePos+3]=(char)(k + 0x30);
// apres la virgule :
switch (Var & 0x03)
{
case 0 : table[tablePos+5]=0x30; // xxxx.00
table[tablePos+6]=0x30; break;
case 1 : table[tablePos+5]=0x32; // xxxx.25
table[tablePos+6]=0x35; break;
case 2 : table[tablePos+5]=0x35; // xxxx.50
table[tablePos+6]=0x30; break;
case 3 : table[tablePos+5]=0x37; // xxxx.75
table[tablePos+6]=0x35; break;
}
}
//-----------------------------------------------------------------------------
void SendMsg(void)
{
while (*TXPtr)
{
while (U1STAbits.UTXBF);
U1TXREG = *TXPtr++;
}
}
//------------------------------------------------------------------------
// SendData sends the debug information on the uart at 19200 baud
void SendData()
{
// Codage ASCII de la donnée hexa
ConvHexa( TimeStamp, OffsetTimeStamp, OutData); // TimeStamp en Hexa
// Sensor0_Tr=(Sensor0_T >> 3) & 0xFFF;
// ConvDec( Sensor0_Tr, OffsetSensor0_Tr, OutData); // Sensor0_T en Hexa
TXPtr = &OutData[0];
SendMsg();
}
//------------------------------------------------------------------------
// Converti Hour, Min, Sec en ASCII sur LCDbuffer
void print_heure_LCDbuffer()
{
unsigned int k;
unsigned char c;
// Codage ASCII de la donnée
k = Hour;
c = k/10;
if (c > 0) k = k - c*10;
LCDbufferTmp[0] = (c + 0x30);
LCDbufferTmp[1] = (char)(k + 0x30);
k = Min;
c = k/10;
if (c > 0) k = k - c*10;
LCDbufferTmp[3] = (c + 0x30);
LCDbufferTmp[4] = (char)(k + 0x30);
k = Sec;
c = k/10;
if (c > 0) k = k - c*10;
LCDbufferTmp[6] = (c + 0x30);
LCDbufferTmp[7] = (char)(k + 0x30);
}
//-----------------------------------------------------------------------------
// Timer1 interrupt fait le calcul et l allumage des LED
// ISR toutes les 200 us
//---------------------------------------------------------------------
void __attribute__((__interrupt__)) _T1Interrupt( void )
{
IFS0bits.T1IF = 0;
if (++tcnt>=tcntPRD)
{// ici on est toutes les secondes
tcnt=0;
TimeStamp++;
if (++Sec==60)
{
Sec=0;
if (++Min==60)
{
Min=0;
if (++Hour==24) Hour=0;
}
}
sprintf(LCDbuffer, "Il est :");
LCD3310_GotoXY(0,1);
LCD3310_SendMsg(LCDbuffer);
InterruptLED=1;
sprintf(LCDbuffer, "%02d:%02d:%02d",Hour, Min, Sec);
InterruptLED=0;
LCD3310_GotoXY(0,2);
LCD3310_SendMsg(LCDbuffer);
InterruptLED=1;
print_heure_LCDbuffer();
InterruptLED=0;
LCD3310_GotoXY(0,3);
LCD3310_SendMsg(LCDbufferTmp);
}
// communication dsPIC -> PC
if (!--SeqComm) {
SeqComm=SeqCommMax;
Flags.SendData=1;
}
}
//-----------------------------------------------------------------------------
//Main routine
int main(void)
{
unsigned int j;
setup_ports();
//----- Debug -----------
LCD3310_RST=1; // ziada
// DelayNmSec(50); // tempo
DelayNmSec(2000);
LCD3310_RST=0; // Reset LCD
// DelayNmSec(250);
DelayNmSec(1800);
LCD3310_RST=1; // pas de RST LCD
InitPWM_HP_LCD3310();
InitSPI_LCD3310();
LCD3310_Clear();
LCD3310_GotoXY(0,0);
// debug
//while(1); // bloque ici
//// écrit une chaine d'essai
// LCD3310_WriteChar('L');
// LCD3310_WriteChar('o');
// LCD3310_WriteChar('t');
// LCD3310_WriteChar('f');
// LCD3310_WriteChar('i');
LCD3310_SendMsg(Phrase);
// debug
//while(1); // bloque ici
//-------------------------
InitVar();
InitUART();
initTimer();
InterruptLED=0;
Flags.Running=1;
while(1)
{
if (Flags.SendData)
{
SendData(); // send present fs serially
Flags.SendData = 0; // clear flag
}
} // end of while (1)
}
//=============================================================================
//Error traps
//-----------------------------------------------------------------------------
//Oscillator Fail Error trap routine
void _ISR _OscillatorFail(void)
{
InterruptLED=0;
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Address Error trap routine
void _ISR _AddressError(void)
{
InterruptLED=0;
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Stack Error trap routine
void _ISR _StackError(void)
{
InterruptLED=0;
while(1); //Wait forever
}
//-----------------------------------------------------------------------------
//Math (Arithmetic) Error trap routine
void _ISR _MathError(void)
{
InterruptLED=0;
while(1); //Wait forever
}
//---------------------------------------------------------------------
// This is a generic 1ms delay routine to give a 1mS to 65.5 Seconds delay
// For N = 1 the delay is 1 mS, for N = 65535 the delay is 65,535 mS.
// Note that FCY is used in the computation. Please make the necessary
// Changes(PLLx4 or PLLx8 etc) to compute the right FCY as in the define
// statement above.
//---------------------------------------------------------------------
void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
for(j=0;j < MILLISEC;j++);
}
//---------------------------------------------------------------------