/* DVM7135 Project Dual Channel Digital Volt Meter Interfacing two ICL7135 4 1/2DVM chips to the 89S52 Microcntroller Signal input +/-1.9999V 100 uV sensitivity Serial interface: RS232C 9600 8n1 Power Supply: 220VAC 5VA Copyright(c) 2011 Wichit Sirichote, wichit.sirichote@gmail.com, September 5, 2011 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "AT89X52.H" #include "stdio.h" sbit CLK= P1^7; sbit DIN= P1^6; sbit LOAD= P1^5; sbit D5 = P0^4; sbit P2D5 = P2^4; int digit=5; int digit2=5; char sbuffer[8]; char sbuffer2[8]; unsigned char buffer[16]; char command; short ready=0; short ready2=0; short terminal=1; int V1=0; int tV1,tV2; unsigned int temp16; unsigned long temp32=0; sbit RUN = P1^1; char code convert[10] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b}; /* 7-segment pattern converting array a __ register data f |__| b D7 D6 D5 D4 D3 D2 D1 D0 e |__| c.DP DP a b c d e f g d */ char code prompt[] = "\n\r >"; short pol,ov; short pol2,ov2; #define POLARITY 0x20 #define OVERRANGE 0x40 // shift 32-bit data to 7219 serially shift(long n) { char j; CLK = LOAD = 0; for(j=0; j<32; j++) { DIN = n&0x80000000; // send data to 7219 CLK =1; // pulse CLK CLK =0; n<<=1; // shift left one bit } LOAD =1; // pulse LOAD LOAD =0; } init7219() { shift(0x0a010a01); /* intensity (middle) */ shift(0x0b070b07); /* scan limit 8 digits */ shift(0x09000900); /* no decode mode */ shift(0x0f000f00); /* disable test mode */ shift(0x0c010c01); /* normal operation */ } update7219() { //init7219(); /* reinitialize everytime entering to this function */ temp32=0; temp32 |= buffer[0]; temp32<<=16; temp32|= buffer[8]; shift(0x01000100|temp32); temp32=0; temp32 |= buffer[1]; temp32<<=16; temp32|= buffer[9]; shift(0x02000200|temp32); temp32=0; temp32 |= buffer[2]; temp32<<=16; temp32|= buffer[10]; shift(0x03000300|temp32); temp32=0; temp32 |= buffer[3]|0x80; // put decimal point temp32<<=16; temp32|= buffer[11]|0x80; shift(0x04000400|temp32); temp32=0; temp32 |= buffer[4]; temp32<<=16; temp32|= buffer[12]; shift(0x05000500|temp32); temp32=0; temp32 |= buffer[5]; temp32<<=16; temp32|= buffer[13]; shift(0x06000600|temp32); temp32=0; temp32 |= buffer[6]; temp32<<=16; temp32|= buffer[14]; shift(0x07000700|temp32); temp32=0; temp32 |= buffer[7]; temp32<<=16; temp32|= buffer[15]; shift(0x08000800|temp32); } void ex0_isr (void) interrupt 0 using 1 { if(D5) digit=5; sbuffer[digit]= P0&0x0F; buffer[8-digit]=convert[sbuffer[digit]]; digit--; if(digit==0) ready=1; // read polarity, over range and under range if(P0&POLARITY) pol=1; else pol=0; if(P0&OVERRANGE) ov=1; else ov=0; } void ex1_isr (void) interrupt 2 using 2 { if(P2D5) digit2=5; sbuffer2[digit2]= P2&0x0F; buffer[16-digit2]=convert[sbuffer2[digit2]]; digit2--; if(digit2==0) ready2=1; // read polarity, over range and under range if(P2&POLARITY) pol2=1; else pol2=0; if(P2&OVERRANGE) ov2=1; else ov2=0; } void over_display() { buffer[3]=0x7E; buffer[4]=0x0E; buffer[5]=0; buffer[6]=0; buffer[7]=0; } void over_display2() { buffer[11]=0x7E; buffer[12]=0x0E; buffer[13]=0; buffer[14]=0; buffer[15]=0; } void print_channel1() { // float temp; if(ready) { // ready=0; V1=0; V1 = sbuffer[5]*10000; V1 += sbuffer[4]*1000; V1 += sbuffer[3]*100; V1 += sbuffer[2]*10; V1 += sbuffer[1]; //RUN=0; // display on LED if(pol==0) buffer[2]= 0x01; // put minus sign else buffer[2]=0x00; buffer[3] |=0x80; // put dot to buffer[3] if(ov) over_display(); update7219(); // also send to PC via serial port 9600 8n1 if(pol==0) V1*=-1; tV1= V1; // printf("\n%.4f,",temp); } } void print_channel2() { // float temp; if(ready2) { // ready2=0; V1=0; V1 = sbuffer2[5]*10000; V1 += sbuffer2[4]*1000; V1 += sbuffer2[3]*100; V1 += sbuffer2[2]*10; V1 += sbuffer2[1]; //RUN=0; // display on LED if(pol2==0) buffer[10]= 0x01; // put minus sign else buffer[10]=0x00; buffer[11] |=0x80; // put dot to buffer[3] if(ov2) over_display2(); update7219(); // also send to PC via serial port 9600 8n1 if(pol2==0) V1*=-1; tV2= V1; //printf("%.4f",temp); } } void pause() { unsigned int i; for(i=0; i<50000;i++) continue; } void print_7135() { //buffer[1]=0x06; //buffer[2]=0x4E; //buffer[3]=0x0E; buffer[12]=convert[7]; buffer[13]=convert[1]; buffer[14]=convert[3]; buffer[15]=convert[5]; update7219(); pause(); // wait for a while } void print_terminal() { if(ready&&ready2) { ready=0; ready2=0; printf("\n%dE-4,%dE-4",tV2,tV1); } } char getchar(void) { char c; while(!RI); RI =0; c = SBUF; putchar(c); // echo to terminal return SBUF; } void getcommand() { if (RI) command = getchar(); // else command = -1; /* no cammand has entered */ } void escape_command() { if(command== 0x27) { //terminal^=1; } } void main (void) { SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */ TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */ TH1 = 0xfd; /* TH1: reload value for 9600 baud */ TR1 = 1; /* TR1: timer 1 run */ TI = 1; /* TI: set TI to send first char of UART */ T2CON = 0x00; // timer 2 is used to produce 120KHz for 60Hz and 125kHz for 50Hz T2MOD |= 0x02; TR2 =1; RCAP2H= 0xFF; RCAP2L= 0xEA; // E9 for 120kHz, EA for 125kHz IT0 = 1; // Configure interrupt 0 for falling edge on /INT0 (P3.2) IT1 =1; // falling edge of INT1 EX0 = 1; // Enable EX0 Interrupt EX1 = 1; // enable EX1 interrupt EA = 1; // Enable Global Interrupt Flag RUN=1; // hold init7219(); printf("\nDual Channel Digital VoltMeter"); print_7135(); buffer[0] = convert[2]; buffer[8]= convert[1]; while(1) { getcommand(); escape_command(); print_channel1(); print_channel2(); print_terminal(); } }