/* ********************************************************************** * File GMBADE.C - Rel. 1.1 with uC/51 V. 1.10.09 * * GRIFO(R) via Dell'Artigiano 8/6 40016 S. Giorgio di Piano (BO) * * Tel. +39 051 892052 Fax. +39 051 893661 * * http://www.grifo.com http://www.grifo.it * * sales@grifo.it tech@grifo.it grifo@grifo.it * * by Angelini Gianluca date 11.07.03 * ********************************************************************** 11/07/03: GMBADE.C - Rel. 1.1 - By Angelini Gianluca According to Mini Module selected, if analog input signal on CN4 is available, this demo offers two possibilities: calibration or acquisition. First action determinates a calibration coefficent using an external reference voltage provided by the user and stored in Mini Module internal EEPROM. Second action loads calibration coefficent from EEPROM, acquires and shows continuously on console the analog input combination, both uncalibrated and calibrated. Demo can be used without problems with range 0..2.5 V and 0..10 V. Note To avoid problems do not use complex operations on a single source line, especially inside procedures by using their parameters or their local variables. */ /**************************************************************************** Header, constant, data structure, etc. ****************************************************************************/ #include "canarye.h" #include #include #define FALSE 0x00 // Boolean value #define TRUE 0xFF #define LF 0x0A // ASCII codes #define CRET 0x0D #define TOUTEEP 5000 // Time out constant for EEPROM management // Global variables for I2C BUS management near unsigned char resi2c; // I2C BUS error variable bit unsigned char SDACAN @ 0xA1; // SDA pin on CAN GMx=P2.1 bit unsigned char SCLCAN @ 0xA0; // SCL pin on CAN GMx=P2.0 bit unsigned char SDA5115 @ 0xA0; // SDA pin on GMM 5115=P2.0 bit unsigned char SCL5115 @ 0xA1; // SCL pin on GMM 5115=P2.1 // General purpose global variables used by main and procedures near unsigned char minmod,choice,dr,dw,hlp; near unsigned int val; inear unsigned char input[9]; // Console input buffer /**************************************************************************** General purpose functions and card hw sections management functions ****************************************************************************/ unsigned char divappr(unsigned long divid,unsigned long divis) /* Procedure that calculates the 8 bit integer quotient, correctly approximated, between the dividend and the divisor passed as parameters, by using the successive subtractions tecnique. This function is used to reserve the 2K of code required by the same librari functions. */ { unsigned char d; d=0; // Set quotient to zero while (divid>=divis) { divid=divid-divis; d++; } //endwhile divis=divis>>1; // Halves divisor to check the remainder if (divid>=divis) d++; //endif return d; } void init_cpu(void) /* Perform some specific initialization of CPU SFRs */ { EA=0; // Ensures interrupt disabled CKCON=0x00; // Set X1 clock mode = standard mode AUXR=0x0C; // Selects ERAM on external data area EECON=0x00; // Disables internal EEPROM } void iniser(unsigned long baud) /* Initializes the serial line with: Bit x chr = 8 Stop bit = 1 Parity = None Baud rate = baud using timer 1 as baud rate generator. */ { SCON=0x052; // Mode 1, enables receiver TMOD&=0x00F; // Timer 1 in auto-reload mode TMOD|=0x020; TR1=0; // Stops TIMER 1 TH1=(unsigned char)(256-divappr((2*14745600),(384*baud))); // 14.7456 MHz PCON=PCON|0x080; // Sets SMOD=1 for high baud rates TR1=1; // Starts TIMER 1 TI=1; // Sets end of transmission bit for optimized console (SIOTYPE=k) } void clrscr(void) /* Performs the clear screen function for a generic console */ { unsigned char r; putc(CRET); for (r = 0 ; r < 25 ; r++) { putc(LF); // Transmit 25 Line Feeds } //endfor } void notavail(void) /* Shows message of resource not available on selected Mini Module and stop execution */ { printf("Resource not available on Mini Module. "); for(;;); } void delay(unsigned int del) /* Executes a software delay of del milliseconds, calibrated on a 14.7456 MHz CPU Clock */ { unsigned int r,dt1ms; dt1ms=100; // Experimental value for 1 msec. delay do { for (r=0 ; r0); } void setP1234inp(void) /* Sets all the lines of all the ports (P1,P2,P3,P4) del modulo CAN GM1 in input. */ { ADCF=0x00; // Sets P1.x as I/O port P1=0xFF; // Sets Port 1 as INPUT dr=P1; P2=0xFF; // Sets Port 2 as INPUT dr=P2; P3=0xFF; // Sets Port 3 as INPUT dr=P3; P4=0xFF; // Sets Port 4 as INPUT dr=P4; } unsigned int adconv (unsigned char adcan) /* Perform a conversion on adcan channel (0..7) of microprocessor internal A/D section and returns the 10 bits acquired combination */ { unsigned char dl,dh; unsigned int adv; adcan=adcan|0x20; // Configures A/D and selects adcan ADCON=adcan; adcan=adcan|0x08; // Starts conversion ADCON=adcan; while ((ADCON & 0x10)==0); // Waits end of conversion dl=ADDL; // Reads conversion result dh=ADDH; dl=dl & 0x03; // Calculates 10 bits combination adv=dh<<2; adv=adv|dl; return adv; // Returns obtained combination } void riti2c(void) /* Performs a delay for syncronous I2CBUS communication. The delay is sufficient for a 22 MHz clock, X1 modality */ { #asm nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop #endasm } void starti2c(void) /* Generates start sequence for I2C BUS */ { if (minmod=='3') { SCL5115=0; // Start sequence with GMM 5115 SDA5115=1; riti2c(); SCL5115=1; SDA5115=0; riti2c(); SCL5115=0; } else { SCLCAN=0; // Start sequence with CAN GMx SDACAN=1; riti2c(); SCLCAN=1; SDACAN=0; riti2c(); SCLCAN=0; } //endif } void stopi2c(void) /* Generates stop sequences for I2C BUS */ { if (minmod=='3') { SCL5115=0; // Stop sequence with GMM 5115 SDA5115=0; riti2c(); SCL5115=1; SDA5115=1; riti2c(); SCL5115=0; } else { SCLCAN=0; // Stop sequence with CAN GMx SDACAN=0; riti2c(); SCLCAN=1; SDACAN=1; riti2c(); SCLCAN=0; } //endif } void wri2c_bit(unsigned char i2cbit) /* Serializes the D0 bit of i2cbit, on I2CBUS */ { if (minmod=='3') { SCL5115=0; // Sets SDA and generates positive pulse on SCL with GMM 5115 SDA5115=i2cbit; riti2c(); SCL5115=1; riti2c(); SCL5115=0; } else { SCLCAN=0; // Sets SDA and generates positive pulse on SCL with CAN GMx SDACAN=i2cbit; riti2c(); SCLCAN=1; riti2c(); SCLCAN=0; } //endif } unsigned char rdi2c_bit(void) /* Deserializes one bit from I2CBUS and saves it on lsb of the returned value */ { unsigned char biti2c; if (minmod=='3') { SDA5115=1; // Avoids conflicts in SDA acquisition SCL5115=0; // Ensures SCL status riti2c(); SCL5115=1; // Generates positive pulse on SCL and reads SDA biti2c=SDA5115; riti2c(); SCL5115=0; } else { SDACAN=1; // Avoids conflicts in SDA acquisition SCLCAN=0; // Ensures SCL status riti2c(); SCLCAN=1; // Generates positive pulse on SCL and reads SDA biti2c=SDACAN; riti2c(); SCLCAN=0; } //endif return biti2c; } void wri2c_byte(unsigned char i2cbyte) /* Serializes the i2cbyte byte on I2CBUS */ { unsigned char b; for (b = 1; b <= 8; b++) { if ((i2cbyte & 0x80) == 0) // Determines and sets b bit wri2c_bit(0); else wri2c_bit(1); i2cbyte = i2cbyte << 1; } } unsigned char rdi2c_byte(void) /* Deserializes one byte from I2CBUS and saves it in the returned value */ { unsigned char b,tmp; tmp = 0; for (b = 1; b <= 8; b++) { tmp = tmp << 1; tmp = tmp | rdi2c_bit(); // Gets and saves b bit } return tmp; } unsigned char wr_i2c(unsigned char i2csla,unsigned char i2cadd,unsigned char i2cdat) /* Writes the i2cdat byte to i2caddr address of the I2CBUS device that have the slave address i2csla. Returns a boolean flag that signals the operation result: 0=right,1=wrong */ { unsigned char i2cres; i2cres = 0; // Sets right result starti2c(); // Supplies start sequence wri2c_byte(i2csla); // Supplies slave address+W i2cres = i2cres | rdi2c_bit(); // Checks ACK on slave address+W wri2c_byte(i2cadd); // Supplies address i2cres = i2cres | rdi2c_bit(); // Check ACK on address wri2c_byte(i2cdat); // Supplies data i2cres = i2cres | rdi2c_bit(); // Check ACK on data stopi2c(); // Supplies stop sequence return i2cres; // Returns operation result } void pokeb(unsigned int addr, unsigned char dat) /* Writes the dat byte to addr address of external data area */ { *(xdata unsigned char *)addr=dat; // Saves byte in location } unsigned char peekb(unsigned int addr) /* Reads the byte from addr address of external data area and returns it */ { return *(xdata unsigned char *)addr; // Gets byte from location } unsigned char wr_ee(unsigned int eeaddr,unsigned char eedat) /* Writes the eedat byte to eeaddr address of the internal EEPROM and returns a boolean flag that signals the operation result: 0=right,1=wrong */ { unsigned int toee; AUXR=0x2E; // Deselects ERAM and increase MOVX duration EECON=0x02; // Selects microprocessor EEPROM on external data area pokeb(eeaddr,eedat); // Sets dat in EEPROM column latch EECON=0x52; // Supplies EEPROM programmation sequence EECON=0xA2; toee=0; // Initializes timeout programming counter while ((EECON & 0x01) && (toee0) && (toeeCAN GM1 , 2->CAN GM2 , 3->GMM 5115"); printf("Select Mini Module mounted on ZC1 socket (1,2,3):"); do minmod=toupper(getc()); while ((minmod<'1') || (minmod>'3')); clrscr(); // Shows demo program menu` printf("Demo program for A/D input on GMB HR84 in uC/51 - Rel. 1.1 with "); switch (minmod) { case '1': puts("CAN GM1"); break; case '2': puts("CAN GM2"); break; case '3': puts("GMM 5115"); break; } //endswitch if (minmod=='3') // Cycle that waits card ready { // on GMM 5115 do rd_ee(0x07F8,&dr); while (dr!=0); } else { // on CAN GM1, CAN GM2 do { dr=P2_1; starti2c(); wri2c_byte(0xA0); dw=rdi2c_bit(); } while ((dr==0) || (dw==1)); } //endif if (minmod=='1') { puts(""); puts("The analog input section is based on components with tolerances."); puts("To compensate them it is preferible to acquire the analog input through a"); puts("software calibration."); for(;;) // Endless loop { puts(""); printf("Acquisition,Calibration:"); do choice=toupper(getc()); while ((choice!='A') && (choice!='C')); printf("%c\r\n",choice); // Shows valid choice ADCF=0x01; // Sets P1.0 as A/D input ADCLK=0x10; // Sets A/D clock if (choice=='C') { // Calibration modality puts("Connect to pin 8 of CN4 a reference voltage signal near to selected full"); printf("scale value and insert his voltage, in mV (0-10000): "); inputse(input, 8); // Gets unsigned int kcal=(unsigned int)atoi(input);// Determines and save applied voltage kcmb=kcal; // for next elaborations kcmb=(unsigned long) kcal*1023; // Determines applied combination if (kcal>2500) kcmb=kcmb/10000; else kcmb=kcmb/2500; // endif cmb=0; // Determines real combination for (hlp=1;hlp<=64;hlp++) // Performs 64 conversions cmb=cmb+adconv(0); // Adds A/D input 0 conversion // endfor cmb=cmb>>6; // Obtains 64 combinations average kcmb=kcmb*10000; // Obtain calibration coef. with 4 decimal digits kcmb=kcmb/cmb; kcal=(unsigned int)kcmb; printf("\r\nObtained and saved cal. coef.=%d\r\n",kcal); wr_ee(0x07F9,(uchar)(kcal&0xFF)); // Saves calibration coef. in EE wr_ee(0x07FA,(unsigned char)(kcal>>8)); } else { // Acquisition modality rd_ee(0x07F9,&dr); // Loads calibration coef. from EEPROM rd_ee(0x07FA,&dw); kcal=(dw<<8)|dr; // Obtains calibration coef. printf("Loaded cal. coef.=%d\r\n",kcal); puts("Connect to pin 8 of CN4 an analog signal included in range selected with"); puts("J6 and verify the following combinations. Press a key to exit"); puts("CH0 acquired,calibrated"); do { putc(CRET); cmb=adconv(0); // Converts A/D input 0 printf(" %4d",cmb); // Shows acquired combination kcmb=(unsigned long) cmb*kcal; // Determines calibrated combination cmb=(unsigned int)(kcmb/10000); printf(" %4d",cmb); // Shows calibrated combination delay(300); // Avoids overflow on console and allows reading } while (! kbhit()); getc(); putc(LF); } // endif } // endfor (;;) // End of endless loop } else notavail(); // Resource not available on selected Mini Module //endif }