Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
private
/
Projet
:
main.c
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
/* =========================================================================== Main.c - Simple ?? program for Axiom CML12SDP256 board Version: 1.0 Author: Jason Siegel Compiler: GNU for 68HC11 & 68HC12 (www.gnu-m68hc11.org) This is freeware - use as you like ============================================================================== ------------------------------------------------------------------------------ */ // Constant Definitions // -------------------- #define Eclock 24000000 // 24Mhz crystal clock frequency (NOICE) //#define Eclock 8000000 // 8Mhz crystal clock frequency (MON12) // this board has a 4Mhz osc clock //#define CLKX ((Eclock/1000000)/4) - 1 // pll enable for Eclock #define CLKX 0x05 // values for baud registers, based on clock frequency. #define Baud115200 (Eclock/16)/115200 #define Baud57600 (Eclock/16)/57600 #define Baud38400 (Eclock/16)/38400 #define Baud19200 (Eclock/16)/19200 #define Baud9600 (Eclock/16)/9600 #define ARRAYSIZE 40 #define SENDFLAG 4 // 1488 //SPI STATUS REGISTER #define SPTEF 0x20 #define SPIF 0x80 #include "..\ports_d256.h" #include "lcd.h" #include "keypad.h" #include "serial.h" // RAM Variables // ------------- unsigned long timeout1; // general purpose timeout. unsigned int count1; // general purpose counter unsigned int count4; // general purpose counter unsigned int count5; unsigned int TC6Val; // output compare timer value unsigned char Sflag; unsigned char Sec15flag; unsigned int Npulses=0; unsigned int Last_Npulses=0; unsigned char R_data=0; int Last_serial_status; int spare_index=0; char keyval; unsigned long ELEC_COST=3265; //electric cost * 100000 unsigned char min=0x58, sec=0x0, hr=0x09, dow=0x04, date=0x23, mon=0x10, yr=0x03; char output[40]; // i SHould put this in external SRAM so that the data is saved if the power goes out. struct _timedate { unsigned char sec; unsigned char min; unsigned char hour; unsigned char day; unsigned int N_counts_interval; } timestamp[ARRAYSIZE]; int Current_index; unsigned char month=11; //not yet implemented unsigned int year=2004; //not yet implemented long Current_cost; // Function Prototypes // ------------------- void end_here(); void SER_RECEIVE() __attribute__((interrupt)); void TOC6Handle() __attribute__((interrupt)); void InitPLL(); void setup_stuff(); void setup_SPI1(); void init_DS1305(); void reset_spi(void); void wbyte_spi(unsigned char); unsigned char rbyte_spi(void); void write_serial(); long Calc_Proj_cost(int Nseg, int i); void Calc_Curr_cost(int i); int twokey_DS1305_num(char keys[2]); int key_num(char key); main(){ long i=0; int couner_ii=0; int indexD=0; /* input Target cost < $1000 Cost of Electricity ~0.000001 Time on clock. Year Month Day(1-31) hour min sec OUTPUT Data Array: Projected Cost. * Project=Current_cost/Nseg* Nseg_month Current Cost * can be calculated on demand. SUM(N_counts_interval(i) * cost of elect) up to i Day Hour Min N_counts in Interval At current rate of consumption what is the project cost for the end of the month. STOP Running after 10 mins taking data Only Print out data thru Current date, since begin of Month. Write a float to ascii funtion. or find one Use DS1305 interrupt to control timing, alarm every sec, count to 15.... */ asm("sei"); // disable interrupts InitPLL(); // Initialize PLL // Initialize Virtual Interrupt Vectors for ruhning under serial debugger (MON12/NOICE) *(void(**)())0x3fe2 = TOC6Handle; // set Timer Output Compare 7 vector *(void(**)())0x3fD6 = SER_RECEIVE; // set interrupt routine for Serial Reviever $FFD6 // *(void(**)())0x3fCC = PortHhandle; // set interrupt routine for Serial Reviever $FFD6 //InitSerial(Baud9600); // Initialize Serial Port 1 Baud rate InitSerial(Baud115200); //InitATD(); //this funtion sets up the A/D. no longer used. setup_stuff(); //this funtion sets up the couter timer, and pulse accumulator. setup_SPI1(); //setup serial interface to DS1305 unsigned char ioport = 0; // default output to port sci0 puts("\nYou should see PT6 toggling at 500us "); LCDInit(); // initialize LCD InitKeypad(); // prompt user for date and time. supply current settings. init_DS1305(); //set date and time. asm("cli"); // enable interrupts lcd_cmd(0x01); // clear display and home cursor for (i=0; i<48000;i++); //wait 2ms // prompt for engery cost and spending goal. LCDputs("Set Elec Cost? Y/N: "); keyval= getkeypad(); if(keyval=='9'){ ELEC_COST=0; couner_ii=0; LCDputs("Use 5 digits "); LCDputs("Enter Rate*100,000 "); LCDputs(":"); do{ keyval= getkeypad(); LCDputch(keyval); if( keyval !='#' ) ELEC_COST= 10*ELEC_COST + key_num(keyval); couner_ii++; } while( (couner_ii < 5) && ( keyval !='#' ) ); } lcd_cmd(0x01); // clear display and home cursor for (i=0; i<48000;i++); //wait 2ms // endless loop while(1){ if(Sflag == 1){ // if time expired 1/2 sec Sflag=0; lcd_cmd(0x02); //Cursor to Home asm("sei"); // disable interrupts Npulses=PACN2+(PACN3<<4); //this line reades the Pulse accumulator. // LCDputs("here every sec "); PTT = 0x0001; // enable RTC - CS high wbyte_spi(0); // seconds register read address rbyte_spi(); // dummy read wbyte_spi(0); sec = rbyte_spi(); // read seconds register wbyte_spi(0); min = rbyte_spi(); // ditto minutes wbyte_spi(0); hr = rbyte_spi(); // and so on wbyte_spi(0); dow = rbyte_spi(); wbyte_spi(0); date = rbyte_spi(); wbyte_spi(0); mon = rbyte_spi(); wbyte_spi(0); yr = rbyte_spi(); PTT = 0; // disable RTC - CS low asm("cli"); // enable interrupts sec=((sec & 0xF0)>>4)*10+(sec & 0xF); min=((min & 0xF0)>>4)*10+(min & 0xF); hr=((hr & 0x30)>>4)*10+(hr & 0xF); date=((date & 0xF0)>>4)*10+(date & 0xF); //itoa(date,output); //LCDputs(output); LCDputs("-Date "); itoa(hr,output); LCDputs(output); LCDputs(":"); itoa(min,output); LCDputs(output); LCDputs(":"); itoa(sec,output); LCDputs(output); LCDputs(" Counts:"); //itoa(count1,output); itoa(Npulses-Last_Npulses,output); LCDputs(output); LCDputs(" "); // store 1 value Every 15 secs if(sec%15==0 && Sec15flag==0 && (indexD < ARRAYSIZE)){ // here every 15 secs Sec15flag=1; timestamp[indexD].N_counts_interval= Npulses-Last_Npulses; timestamp[indexD].sec=sec; timestamp[indexD].min=min; timestamp[indexD].hour=hr; indexD++; Last_Npulses=Npulses; //if (indexD>ARRAYSIZE) indexD=0; //start a new month. // fix when we add DS1305 write_serial(); } if(sec%15==1) Sec15flag=0; // we dont want to run 2x per ++count1; } } } void end_here(){ return; // this is here for a constant place to put a breakpoint } //--------------------------------------------------------------------------- // change the clock frequency using the PLL void InitPLL(){ unsigned char stat; // Enable the PLL SYNR = CLKX; // set Eclock frequency do{ // wait for PLL to lock... stat = CRGFLG; // get PLL flags }while((stat & 0x08) == 0); CLKSEL = 0x80; // turn PLL on } //=== INTERRUPT ROUTINES ===================================================== /*---------------------------------------------------------------------------- TOC6Handle ---------- Interrupt Handler routine for TOC6 ----------------------------------------------------------------------------*/ void __attribute__((interrupt))TOC6Handle(){ // here every 500us TFLG1 = 0x40; // clear C6 output capture flag - IDLE TC6 = TC6 + TC6Val; // Set new Timer 6 Output compare Value ++timeout1; // incriment timeout counter if(++count4 > 1000){ // if time to update counters // here every 1/2 second // senddata_flag++; Sflag=1; count4=0; } } void __attribute__((interrupt)) SER_RECEIVE(){ // asm("sei"); // disable interrupts //char data[40]; Last_serial_status=SC0SR1; if(Last_serial_status & 0x20 ) {// there is something in the Recieve Data Register R_data=SC0DRL; // putch(R_data); //echo back to host if ( R_data=='g' ) { write_serial(); } else if ( R_data=='d' ) { reset(); } } } //=== END INTERRUPT ROUTINES ================================================== void setup_stuff() { // Initialize Timers // BUS SPEED - Eclock // On this board (CML12DP256) on power up, the bus clock defaults to 2Mhz (osc / 2) // operating MON12 debugger the bus clock is running at 8Mhz // operating NoICE kernel the bus clock is running at 24Mhz // TMSK2 (now called TSCR2 in the new datasheet) changes the timer PRESCALER TMSK2 = 0x00; // Prescaler divide by 1 (TSCR2) - makes timer system run at Bus speed exactly (no prescaler) // TMSK2 = 0x01; // Prescaler divide by 2 (TSCR2) - makes timer system run at Bus speed / 2 // TMSK2 = 0x03; // Prescaler divide by 8 (TSCR2) - makes timer system run at Bus speed / 8 // TMSK2 = 0x04; // Prescaler divide by 16 (TSCR2) - makes timer system run at Bus speed / 16 (ie. 24/16 = 1.5) // TMSK2 = 0x05; // Prescaler divide by 32 (TSCR2) - makes timer system run at Bus speed / 32 TSCR = 0x80; // enable timer /* 1/bus speed = time period (half cycle time) IF USING NO PRESCALER: 1/24 = 0.041667 (41.7 nano-seconds) we want 500us, so 500 / 0.041667 = 12000 this will give us a 500us time period (half cycle time) IF USING divide by 2 prescaler (TMSK2=0x01) 1/12 = 0.083333 (83.3 nano-seconds) we want 500us, so 500 / 0.083333 = 6000 this will give us a 500us time period (half cycle time) */ TC6Val = 12000; // output compare time with NO prescaler (24mhz) // TC7Val = 6000; // output compare time with /2 prescaler TC6 = TCNT + TC6Val; // Set Timer 6 Output compare Value TIOS = 0x40; // set channel 6 to output compare TCTL1 = 0x40; // toggle OC7 output line on output compare TMSK1 = 0x40; // enable Channel 6 Interrupt Request (TIE) TFLG1 = 0x40; // clear C6 output capture flag - IDLE TFLG2 = 0x00; // clear timer overflow flag DDRT=0x01;// USE T0 for output to control DS1305 // Here is where we setup the pulse accumulator on channel T7 // we want negative edge and to disable interrupts PACTL=0x40; //This register contains all settings for Pulse accumulator A. // see section 3.3.15 PACTL � 16-Bit Pulse Accumulator A Control Register // of ECT_16B8C Block User Guide for register descriptions // reset all counters and flags count1=0; count4=0; timeout1=0; Sflag=0; } void setup_SPI1(){ // SPI Port 1 uses PP0-4 // PP3 SS1 Serial Peripheral Interface 1 slave select output in master mode, // input for slave mode or master mode. // PP2 SCK1 Serial Peripheral Interface 1 serial clock pin // PP1 MOSI1 Serial Peripheral Interface 1 master out/slave in pin // PP0 MISO1 Serial Peripheral Interface 1 master in/slave out pin // #define SPI1CR1 _P(0xF0) // spi 1 control1 reg // #define SPI1CR2 _P(0xF1) // spi 1 control2 reg // #define SPI1BR _P(0xF2) // spi 1 baud reg // #define SPI1SR _P(0xF3) // spi 1 status reg hi // #define SP1DR _P(0xF5) // spi 1 data reg // 3.3.1 SPI Control Register 1 // Register Address: $___0 // Bit 7 6 5 4 3 2 1 Bit 0 // SPIE SPE SPTIE MSTR CPOL CPHA SSOE LSBFE // Reset: 0 0 0 0 0 1 0 0 // LCD 0 1 0 1 0 0 1 0 0x52; // desired 0 1 0 1 0 1 0 0 0x54; // SPIE � SPI Interrupt Enable Bit // This bit enables SPI interrupts each time the SPIF or MODF status flag is set. // 1 = SPI interrupts enabled. // 0 = SPI interrupts disabled. // SPE � SPI System Enable Bit // This bit enables the SPI system and dedicates the SPI port pins to SPI system functions. // 1 = SPI port pins are dedicated to SPI functions. // 0 = SPI disabled (lower power consumption). // SPTIE � SPI Transmit Interrupt Enable // This bit enables SPI interrupt generated each time the SPTEF flag is set. // 1 = SPTEF interrupt enabled. // 0 = SPTEF interrupt disabled. // MSTR � SPI Master/Slave Mode Select Bit // 1 = Master mode // 0 = Slave mode // CPOL � SPI Clock Polarity Bit // This bit selects an inverted or non-inverted SPI clock. To transmit data between SPI modules, the SPI // modules must have identical CPOL values. // 1 = Active-low clocks selected; SCK idles high // 0 = Active-high clocks selected; SCK idles low // CPHA � SPI Clock Phase Bit // This bit is used to shift the SCK serial clock. // 1 = The first SCK edge is issued at the beginning of the 8-cycle transfer operation // 0 = The first SCK edge is issued one-half cycle into the 8-cycle transfer operation // SSOE � Slave Select Output Enable // The SS output feature is enabled only in the master mode by asserting the SSOE as shown in Table // MOD // FEN SSOE Master Mode Slave Mode // 0 0 SS not used by SPI SS input // 0 1 SS not used by SPI SS input // 1 0 SS input with MODF feature SS input // 1 1 SS output SS input // LSBFE � SPI LSB-First Enable // This bit does not affect the position of the msb and lsb in the data register. Reads and writes of the data // register always have the msb in bit 7. // 1 = Data is transferred least significant bit first. // 0 = Data is transferred most significant bit first. // 3.3.2 SPI Control Register 2 // Register Address: $___1 // Bit 7 6 5 4 3 2 1 Bit 0 // 0 0 0 MODFEN BIDIROE 0 SPISWAI SPC0 // Reset: 0 0 0 0 0 0 0 0 // LCD 0 0 0 1 0 0 0 0 // MODFEN � Mode Fault Enable Bit // This bit when set allows the MODF flag to be set. If the MODF flag is set, clearing the MODFEN does // not clear the MODF flag. If the SPI is enabled as master and the MODFEN bit is low, then the SS pin // is not used by the SPI. // When the SPI is enabled as a slave, the SS is available only as an input regardless of the value of // MODFEN. // 1 = Enable setting the MODF error // 0 = Disable the MODF error // BIDIROE � Output enable in the Bidirectional mode of operation // This bit along with the MSTR bit of SPCR1 is used to enable the output buffer when the SPI is // configured in bidirectional mode. // 1 = Output buffer enabled // 0 = Output buffer disabled // SPISWAI � SPI Stop in Wait Mode Bit // This bit is used for power conservation while in wait mode. // 1 = Stop SPI clock generation when in wait mode // 0 = SPI clock operates normally in wait mode // SPC0 � Serial Pin Control Bit 0 // With the MSTR control bit, this bit enables bidirectional pin configurations as shown in Table 3-3. MODRR=0; //dont redirect anything // 3.3.3 SPI Baud Rate Register // Turn on Spi SPI1CR1 = 0x54; SPI1CR2 = 0x00; // to enable /SS SPI1CR1 = 0x56; SPI1CR2 =0x10; SPI1BR = 0x03; // set up Spi baud clock rate div by 16 // SPI1BR = 0x77; // set up Spi baud clock rate div by 2048 SPI1CR1 &= 0xfffd; SPI1CR1 |= 0x0002; // set spe, new values take effect // SPSCR = 0x0096; // SPR0, SPMSTR, CPHA, SPE // SPDSR = 0x0007; // 8-bit size // SPSCR &= 0xfffd; // clear spe, resets SPI (partial) // SPSCR |= 0x0002; // set spe, new values take effect // GPIO_B_PER = 0x00f3; // use GPIOB3 as CS for RTC // GPIO_B_DDR = 0x000c; // direction is output //SPSCR // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // MSB: SPRF ERRIE ovrf modf spte modfen spr1 spr0 sprie spmstr cpol cpha spe spite // 0000 0000 1001 0110 //void reset_spi() // SPSCR = 0x0096; // SPR0, SPMSTR, CPHA, SPE // SPDSR = 0x0007; // 8-bit size // SPSCR &= 0xfffd; // clear spe, resets SPI (partial) // SPSCR |= 0x0002; // set spe, new values take effect } /******************************************************* * init_DS1305() ******************************************************/ void init_DS1305(){ char grab_key_data=0; char anykeys[2]; long i; LCDputs("Initializing ds1305 "); //use portT pin 0 to control CS of DS1305 PTT = 0; // disble RTC - CS low PTT = 0x01; // enable RTC - CS high //burst mode?? wbyte_spi(0x87); // control register write address rbyte_spi(); // dummy read wbyte_spi(0x8); // enable alarm1 rbyte_spi(); wbyte_spi(0x8); // enable alarm1 rbyte_spi(); wbyte_spi(0x8); // enable alarm1 rbyte_spi(); wbyte_spi(0x8); // enable alarm1 rbyte_spi(); PTT = 0; // disble RTC - CS low PTT = 0; // disble RTC - CS low PTT = 0x01; // enable RTC - CS high //burst mode?? wbyte_spi(0x8f); // control register write address rbyte_spi(); // dummy read wbyte_spi(0x1); // disable write protect enable alarm1 rbyte_spi(); PTT = 0; // disble RTC - CS low //set trickle chager PTT = 0; // disble RTC - CS low PTT = 0x01; // enable RTC - CS high //burst mode?? wbyte_spi(0x91); // Trickle Charger rbyte_spi(); // dummy read wbyte_spi(0xA7); // 1diode 8K ohm rbyte_spi(); PTT = 0; // disble RTC - CS low LCDputs(" "); // R_data=0; LCDputs("Set Time: Y/N? "); //print current time here.. //READ CURRENT TIME PTT = 0x0001; // enable RTC - CS high wbyte_spi(0); // seconds register read address rbyte_spi(); // dummy read wbyte_spi(0); sec = rbyte_spi(); // read seconds register wbyte_spi(0); min = rbyte_spi(); // ditto minutes wbyte_spi(0); hr = rbyte_spi(); // and so on wbyte_spi(0); dow = rbyte_spi(); wbyte_spi(0); date = rbyte_spi(); wbyte_spi(0); mon = rbyte_spi(); wbyte_spi(0); yr = rbyte_spi(); PTT = 0; // disable RTC - CS low sec=((sec & 0xF0)>>4)*10+(sec & 0xF); min=((min & 0xF0)>>4)*10+(min & 0xF); hr=((hr & 0x30)>>4)*10+(hr & 0xF); date=((date & 0xF0)>>4)*10+(date & 0xF); //itoa(date,output); //LCDputs(output); LCDputs("-Date "); itoa(hr,output); LCDputs(output); LCDputs(":"); itoa(min,output); LCDputs(output); LCDputs(":"); itoa(sec,output); LCDputs(output); // check user input min=0x65; hr=0x25; grab_key_data = getkeypad(); //putch(grab_key_data); if(grab_key_data=='9'){//set time //prompt for input here: do{ lcd_cmd(0x01); // clear display and home cursor for (i=0; i<48000;i++); //wait 2ms LCDputs("Please Enter Hr :"); anykeys[0]= getkeypad(); LCDputch(anykeys[0]); anykeys[1]= getkeypad(); LCDputch(anykeys[1]); hr = twokey_DS1305_num(anykeys); } while( hr > 0x24); hr = (hr| 0x40);//set 24 hr mode is bit 6 do{ lcd_cmd(0x01); // clear display and home cursor for (i=0; i<48000;i++); //wait 2ms LCDputs("Please Enter Min :"); anykeys[0]= getkeypad(); LCDputch(anykeys[0]); anykeys[1]= getkeypad(); LCDputch(anykeys[1]); min = twokey_DS1305_num(anykeys); }while(min > 0x59); lcd_cmd(0x01); // clear display and home cursor for (i=0; i<48000;i++){} //wait 2ms LCDputs("Setting time..... "); PTT = 0x001; // enable RTC - CS high wbyte_spi(0x80); // select seconds register write address rbyte_spi(); // dummy read wbyte_spi(0); // seconds register data rbyte_spi(); wbyte_spi(min); // minutes register rbyte_spi(); wbyte_spi(hr); // hours register rbyte_spi(); wbyte_spi(dow); // day of week register rbyte_spi(); wbyte_spi(date); // date register rbyte_spi(); wbyte_spi(mon); // month register rbyte_spi(); wbyte_spi(yr); // year register rbyte_spi(); PTT = 0; // disble RTC - CS low } return; } void wbyte_spi( unsigned char wbyte) // ------ write one byte ------- { while (!(SPI1SR & SPTEF)); // wait for transmitter empty flag SP1DR = wbyte; } unsigned char rbyte_spi(void) // -------- read one byte ---------- { while (!(SPI1SR & SPIF)); // wait for receiver full flag return(SP1DR); } long Calc_Proj_cost(int Nseg, int i) { return (float)Current_cost/(float)(i+1)*(float)(Nseg); } void Calc_Curr_cost(int i){ Current_cost += timestamp[i].N_counts_interval*(long)ELEC_COST/1000; // in cents } void write_serial(){ //putch('\n'); //Only Print out data thru Current date, since begin of Month. Current_cost=0; // puts("Format: Projected Cost, Current Cost, Month, Day, HH ,MM, SS, N_counts, Rate "); putch('\n'); for(spare_index=0; spare_index < ARRAYSIZE ; spare_index++) { Calc_Curr_cost(spare_index); //must be called first // writing out cost in cents puti((unsigned long)(Calc_Proj_cost(ARRAYSIZE, spare_index)));// puti(Projected_cost); putascii puts(", "); puti((unsigned long)(Current_cost)); //puti(Current_cost); //add put float here puts(", "); puti(month); puts(", "); puti(timestamp[spare_index].day); puts(", "); puti(timestamp[spare_index].hour); // output the current count to serial port puts(", "); puti(timestamp[spare_index].min); puts(", "); puti(timestamp[spare_index].sec); puts(", "); puti(timestamp[spare_index].N_counts_interval); puts(", "); puti(ELEC_COST); putch('\n'); } } int twokey_DS1305_num(char keys[2]){ int rval=0; switch (keys[1]){ case '1': rval=1; break; case '2': rval=2; break; case '3': rval=3; break; case '4': rval=4; break; case '5': rval=5; break; case '6': rval=6; break; case '7': rval=7; break; case '8': rval=8; break; case '9': rval=9; break; case '0': rval=0; break; default: rval=0; break; } switch (keys[0]){ case '1': rval+=0x10; break; case '2': rval+=0x20; break; case '3': rval+=0x30; break; case '4': rval+=0x40; break; case '5': rval+=0x50; break; case '6': rval+=0x60; break; case '7': rval+=0x70; break; case '8': rval+=0x80; break; case '9': rval+=0x90; break; case '0': rval+=0; break; default: rval+=0; break; } return rval; } int key_num(char key){ int rval=0; switch (key){ case '1': rval=1; break; case '2': rval=2; break; case '3': rval=3; break; case '4': rval=4; break; case '5': rval=5; break; case '6': rval=6; break; case '7': rval=7; break; case '8': rval=8; break; case '9': rval=9; break; case '0': rval=0; break; default: rval=0; break; } return rval; }