Hao Zhang
unread,Oct 13, 2011, 5:21:48 PM10/13/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to 3K04 project grp
/* Turn off watchdog timer */
#pragma config WDT=OFF
/* Set oscillator mode to be HS (high speed) */
#pragma config OSC=HS
#include <p18cxxx.h>
#include <delays.h>
#include <math.h>
/* Frequency of the oscillator */
#define FOSC 4000000
/* Baud rate for serial communication */
#define BAUD_RATE 57600
/* Timer0 interval in microseconds */
#define TIMER0 500000
/* ANSI escape sequences */
#define ANSI_ESC "\033["
#define ANSI_CLEAR_SCREEN (ANSI_ESC"2J")
#define ANSI_CLEAR_LINE (ANSI_ESC"K")
#define ANSI_SAVE_CURSOR (ANSI_ESC"s")
#define ANSI_RESTORE_CURSOR (ANSI_ESC"u")
/* A simple cyclic buffer implementation */
/* The size of such buffer is 2^5 = 32 */
#define BUF_BITS 5
#define BUF_SIZE (1 << BUF_BITS)
#define BUF_MASK (BUF_SIZE - 1)
/* Initialize buffer */
#define BUF_INIT(buf) \
do { \
(buf).head = (buf).tail = 0; \
} while (0)
/* Pop an element from the head of the FIFO buffer */
#define BUF_GET(buf) \
((buf).data[(buf).head++ & BUF_MASK])
/* Append an element into the end of the FIFO buffer */
#define BUF_ADD(buf, c) \
do { \
(buf).data[(buf).tail & BUF_MASK] = (c); \
(buf).tail++; \
} while (0)
/* Append an array of elements into the buffer */
#define BUF_ADDSTR(buf, str) \
do { \
char __i; \
for(__i = 0; (str)[__i]; __i++) { \
BUF_ADD(buf, (str)[__i]); \
} \
} while(0)
/* Test if the buffer is empty */
#define BUF_EMPTY(buf) \
(!(((buf).tail ^ (buf).head) & BUF_MASK))
/* Test if the buffer is full */
#define BUF_FULL(buf) \
(!((((buf).tail + 1) ^ (buf).head) & BUF_MASK))
/* Return the number of elements in the buffer */
#define BUF_LEN(buf) \
(((buf).tail - (buf).head) & BUF_MASK)
/* A struct for the cyclic buffer */
struct buffer {
char data[BUF_SIZE];
volatile char head;
volatile char tail;
};
/* Sending buffer */
struct buffer txbuf;
/* Receiving buffer */
struct buffer rcbuf;
/* Interrupt handler function */
void intr_handler(void);
/* Setting interrupt entrance on PIC18 */
#pragma code intr_section = 0x8
void intr_entry(void) {
_asm goto intr_handler _endasm
}
#pragma code
/* Interrupt handler function */
#pragma interrupt intr_handler
void intr_handler(void) {
/* If the microcontroller received a byte */
if (PIR1bits.RCIF) {
/* Add the byte into receiving buffer */
BUF_ADD(rcbuf, RCREG);
}
/* If the microcontroller sent a byte */
if (PIR1bits.TXIF) {
/* If there is nothing to send (the sending buffer is empty)
*/
if (BUF_EMPTY(txbuf)) {
/* Turn off sending interrupt */
PIE1bits.TXIE = 0;
} else {
/* Send the first byte in the sending buffer */
TXREG = BUF_GET(txbuf);
}
}
if (INTCONbits.TMR0IF) {
//INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 0;
}
}
/* Initialize serial port */
void uart_init(void) {
unsigned int i;
/* Set baud rate */
/* BRGH mode */
TXSTAbits.BRGH = 1;
/* BRG16 mode */
BAUDCONbits.BRG16 = 1;
/* Value of the SPBRG registor for the given baud rate. Check
datasheet
to make sure that the combination of BAUD_RATE,FOSC,BRGH,BRG16
produces
a valid SPBRG. */
i = 64 >> ((TXSTAbits.BRGH + BAUDCONbits.BRG16)
* 2);
i = FOSC / BAUD_RATE / i - 1;
SPBRGH = i >> 8;
SPBRG = i & 0xFF;
/* Configure the pins for UART */
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
/* Enable serial port */
RCSTAbits.SPEN = 1;
/* Enable asynchronous mode */
TXSTAbits.SYNC = 0;
/* Enable transmission (sending) */
TXSTAbits.TXEN = 1;
/* Enable receiving */
RCSTAbits.CREN = 1;
/* Enable interrupt priority */
RCONbits.IPEN = 1;
/* Set high priority for sending and receiving interrupt */
IPR1bits.RCIP = 1;
IPR1bits.TXIP = 1;
/* Enable high priority interrupt */
INTCONbits.GIEH = 1;
/* Enable receiving interrupt */
PIE1bits.RCIE = 1;
/* Initialize receiving buffer */
BUF_INIT(rcbuf);
/* Initialize sending buffer */
BUF_INIT(txbuf);
}
/* Initialize Timer0 */
void timer0_init(void) {
/* Clock periods needed to get the time interval */
unsigned long i = (float)FOSC * TIMER0 / 1000000;
/* TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0 */
T0CON = 0b10000000;
/* Set prescaler */
if (i >> 16) {
for (i >>= 1; i >> 16; i >>= 1, T0CON++);
} else {
T0CON |= 8;
}
/* Set TMR0 = 65536 - i, so after i periods, an interrupt will
fire up */
i = (0xFFFF ^ i) + 1;
TMR0H = i >> 8;
TMR0L = i & 0xFF;
/* Clear TMR0IF flag */
INTCONbits.TMR0IF = 0;
/* Enable Timer0 interrupt */
INTCONbits.TMR0IE = 1;
}
/* Initialize ventricle sense */
void sense_init(void) {
/* Set ventricle sense (pin33) to be input */
TRISBbits.TRISB0 = 1;
}
/* Initialize A/D converter */
void adc_init(void) {
/* Enable ventricle sensing (MICRO_VENT_SENSE_BLANK_CNTL) */
TRISDbits.TRISD4 = 0;
PORTDbits.RD4 = 1;
/* Enable atrial sensing (MICRO_ATRIAL_SENSE_BLANK_CNTL) */
TRISDbits.TRISD5 = 0;
PORTDbits.RD5 = 1;
/* Set SCK to be output pin */
TRISCbits.TRISC3 = 0;
/* Set SDI to be input pin */
TRISCbits.TRISC4 = 1;
/* Set SDO to be output pin */
TRISCbits.TRISC5 = 0;
/* Set SS to be input pin */
TRISAbits.TRISA5 = 1;
}
/* Read a number from A/D converter */
unsigned int adc_get(void) {
unsigned int c = 0;
char i;
for (i = 0; i < 16; i++) {
/* Flip clock line (SCK) */
PORTCbits.SCK = 0;
PORTCbits.SCK = 1;
/* Shift buffer */
c <<= 1;
/* Read a bit and place it at the end of the buffer */
c |= PORTCbits.SDI;
}
return c;
}
/* Wait for A/D converter to be ready for reading */
void adc_start(void) {
/* Ask if A/D converter is ready */
PORTCbits.SDO = 0;
PORTCbits.SCK = 0;
PORTCbits.SCK = 1;
PORTCbits.SDO = 1;
/* Wait for reply */
while (!PORTCbits.SDI);
}
/* Turn off the conversation with A/D converter */
void adc_stop(void) {
PORTCbits.SCK = 0;
PORTCbits.SDO = 0;
}
/* Convert an integer to string, similar to printf("%0nd", i) */
char *intstr(unsigned int i, char n) {
static char buf[6];
char j;
/* Get the least significant digit */
buf[4] = '0' + i % 10;
buf[5] = 0;
/* Get the rest digits */
for (i /= 10, j = 3; i; i /= 10, j--) {
buf[j] = '0' + i % 10;
}
/* Fill the leading zeros */
n = (n >= 4 - j) ? n : (4 - j);
for (; j > 4 - n; j--) {
buf[j] = '0';
}
return &buf[j + 1];
}
/* Timer0 event handler */
void on_timer0(void) {
char buf[6];
unsigned int d;
float v;
/* Reset Timer0 */
timer0_init();
/* Start conversation with A/D converter */
adc_start();
/* Save the current cursor position */
BUF_ADDSTR(txbuf, ANSI_SAVE_CURSOR);
/* Get ventricle voltage */
v = 5.0 * adc_get() / 65535;
/* Print integer part */
BUF_ADDSTR(txbuf, intstr(v, 0));
v = modf(v, (void *)0) * 1000;
/* Print decimal point */
BUF_ADD(txbuf, '.');
/* Print decimal part */
BUF_ADDSTR(txbuf, intstr(v, 3));
BUF_ADD(txbuf, ' ');
/* Get atrial voltage */
v = 5.0 * adc_get() / 65535;
/* Print integer part */
BUF_ADDSTR(txbuf, intstr(v, 0));
v = modf(v, (void *)0) * 1000;
/* Print decimal point */
BUF_ADD(txbuf, '.');
/* Print decimal part */
BUF_ADDSTR(txbuf, intstr(v, 3));
BUF_ADD(txbuf, ' ');
/* Stop conversation with A/D converter */
adc_stop();
/* Print ventricle sensing bit */
BUF_ADD(txbuf, '0' + PORTBbits.RB0);
BUF_ADD(txbuf, '\n');
/* Clear rest of the line */
BUF_ADDSTR(txbuf, ANSI_CLEAR_LINE);
/* Restore cursor position */
BUF_ADDSTR(txbuf, ANSI_RESTORE_CURSOR);
/* Enable sending interrupt */
PIE1bits.TXIE = 1;
}
/* UART event handler */
void on_uart(void) {
char c;
char d;
BUF_ADDSTR(txbuf, "\n\r");
/* Read one byte from the receiving buffer */
c = BUF_GET(rcbuf);
/* Get the first hex code of the byte */
d = c >> 4;
d += (d < 10) ? '0' : ('a' - 10);
/* Put the code in sending buffer */
BUF_ADD(txbuf, d);
/* Get the second hex code of the byte */
d = c & 0xF;
d += (d < 10) ? '0' : ('a' - 10);
/* Put the code in sending buffer */
BUF_ADD(txbuf, d);
BUF_ADD(txbuf, ' ');
/* Now the sending buffer is non-empty, we enable
transmission interrupt to send the contents in sending
buffer */
PIE1bits.TXIE = 1;
}
char sData[16];
char checkSum;
int index;
/* Main entrance */
void main(void) {
/* Initialize */
sense_init();
uart_init();
timer0_init();
adc_init();
/* Clear screen and append a string to sending buffer */
BUF_ADDSTR(txbuf, ANSI_CLEAR_SCREEN);
//BUF_ADDSTR(txbuf, "Hello!\n\r");
/* Enable sending interrupt */
PIE1bits.TXIE = 1;
index = 0;
while (1) {
/* If the receiving buffer is not empty and there is enough
space in the sending buffer */
if (!BUF_EMPTY(rcbuf) && BUF_GET(rcbuf) == 0x16)
{ //check buffer empty and rcbuf scan for 0x16
index = 0;
sData[0] = 0x16;
checkSum = 0x00; //initial
checksum
//writing sData from rcbuf(receiving buffer)
while(index++ < 16){
sData[index] = BUF_GET(rcbuf);
if(index>2 && index<14) checkSum ^=
sData[index];//calculate checksum
}
//if (checkSum != sData[15]) return 1;//compare
checksumm
/*if (sData[1]==FnCode.mode1)
BUF_ADDSTR(txbuf,"valid fncode");
else if (sData[1]==FnCode.mode2)
BUF_ADDSTR(txbuf,"invalid fncode");*/
}
if (BUF_LEN(txbuf) + 16 < BUF_SIZE && index==16) { //checking
if txbuf has enough space to hold data package
index = -1;
checkSum = 0x00; //initial checksum
//PIE1bits.TXIE = 1;
//writing txbuf(transfer buffer)with
information in sData
while(index++<16){
if(index==15) sData[index] = checkSum;//write
checksum to the last char in sData
BUF_ADD(txbuf,sData[index]);
if(index>2&&index<14) checkSum ^= sData[index]; //
calculate checksum
}
PIE1bits.TXIE = 1; //pull up transfer register
}
/* Put the microcontroller in idle mode */
/* WARNING: If you want to debug the code with MPLAB Sim, you
need to remove the following two lines, since MPLAB Sim
cannot be waked up in idle mode by UART interrupt */
//OSCCONbits.IDLEN = 1;
//Sleep();
}
}