// Graphical-Digital Voltmeter based on the 16-bit microcontroller MSP430g2452
// INSTITUTO TECNOLOGICO DE MEXICALI (ITM) Electronics and Mechatronics Dept. //August 30, 2014. Code Composer Studio version 5.5.0 from www.ti.com
//Authors: Ricardo Jiménez-García, M. Sc., and Iván Romero-Hernández
#include
int c2[7],c3[7]; // declaring two integer vectors named c2[7] and c3[7]
void select_led(int f,int c);//declaring method select_led with arguments f= fila c=column
void ConfigureAdc(void); //declaring method ConfigureAdc
void draw(int a1, int a2,int a3,int a4,int a5,int a6,int a7);//method draw with arguments a1-a7
void number(int num); //declaring method number
void integer_number(int num_ent); //method integer number
void decimal_number(int num_dec); //method decimal_number
void period(void); //method period
void voltimeter(void); //method voltmeter
void graph(void); //method graph
void ftoi(float value); //method ftoi with argument value
float voltage=0; //variable float
int ADC_value=0,oldADC_value=4,ADC_comp=0,ADC_comp2=0,cont=0,vr=0; //declaring long integer variables
int count_dec=0,count_ent=0,volt_dec=0,volt_ent=0,i=0,j=0,g=0;//integer variables initialized in zero
/*
* main.c
*/
/* Now the main routine is created, which indicates what the microcontroller will be executing*/
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
DCOCTL = 0x00; // Selecting internal clock
BCSCTL1 = CALBC1_1MHZ; //Setting internal frequency to 1 MHz
DCOCTL = CALDCO_1MHZ; //Starting the 1 MHz internal frequency
P1DIR = BIT0 + BIT1 + BIT2+BIT4+BIT5+BIT6+BIT7;//Setting port1 Inputs/ Outputs
P1OUT&=~BIT0+BIT1+BIT2+BIT4+BIT5+BIT6+BIT7;//Setting initial MCU outputs on port 1
P2DIR= BIT0 + BIT1 + BIT2+BIT3+BIT4+BIT5;//Setting port 2 as Inputs/Outputs
P2OUT= BIT1+BIT0;//Setting inital state outputs on port 2
while(1) //Opening an infinite cycle
{
voltimeter(); //calling method voltimeter
voltage=(float)ADC_value; //converting variable ADC_value to floating type
voltage=voltage*0.00341; //floating operation to get voltage reading
ADC_comp=oldADC_value-ADC_value; //flag operation for a future condition
ADC_comp2=ADC_value-oldADC_value; //2nd flag operation
ftoi(voltage);//invoking method ftoi to change var voltage from floating to integer
if(ADC_comp>=29|ADC_comp2>=29 );//comparing if variable ADC_comp and ADC_comp2 are greater than 29
{
for(g=0;g<=10;g++)//loop to repeat several times the method graph
{
graph(); //invoking method graph
__delay_cycles(5000); //delay of 5000 cycles
}
oldADC_value=ADC_value; //assigning the comparison’s actual value to a variable that stores the previous value
}
else{ //if the previous condition is not met
integer_number(volt_ent); //then invoke method integer number
period(); //invoking method period
decimal_number(volt_dec); //invoking method decimal_¬number
}
}
}
void graph(void) //creating method graph
{
int b1=0,b2=0,b3=0,b4=0,b5=0,b6=0,b7=0; //declaring integer variables
int adc_count=0;
adc_count=ADC_value/29;//dividing the value of ADC/29 because there are 35 leds, 1024/29=35
if(adc_count<=5) //if the division result is <= than 5
{
switch(adc_count)
{
case 1:b1=1;
break;
case 2:b1=3;
break;
case 3:b1=7;
break;
case 4:b1=15;
break;
case 5:b1=31;
break;
}
}
if(adc_count>5 & adc_count<=10)//if the division greater than 5 and less or equal to 10
{
b1=31;
adc_count=adc_count-5;
switch(adc_count)
{
case 1:b2=1;
break;
case 2:b2=3;
break;
case 3:b2=7;
break;
case 4:b2=15;
break;
case 5:b2=31;
break;
}
}
if(adc_count>10 & adc_count<=15)//if the división is > 10 and <= 15
{
b1=31;
b2=31;
adc_count=adc_count-10;
switch(adc_count)
{
case 1:b3=1;
break;
case 2:b3=3;
break;
case 3:b3=7;
break;
case 4:b3=15;
break;
case 5:b3=31;
break;
}
}
if(adc_count>15 & adc_count<=20)//if the division >15 and <= 20
{
b1=31;
b2=31;
b3=31;
adc_count=adc_count-15;
switch(adc_count)
{
case 1:b4=1;
break;
case 2:b4=3;
break;
case 3:b4=7;
break;
case 4:b4=15;
break;
case 5:b4=31;
break;
}
}
if(adc_count>20 & adc_count<=25)//if the div is >20 and <= 25
{
b1=31;
b2=31;
b3=31;
b4=31;
adc_count=adc_count-20;
switch(adc_count)
{
case 1:b5=1;
break;
case 2:b5=3;
break;
case 3:b5=7;
break;
case 4:b5=15;
break;
case 5:b5=31;
break;
}
}
if(adc_count>25 & adc_count<=30)//if the div >25 and <= 30
{
b1=31;
b2=31;
b3=31;
b4=31;
b5=31;
adc_count=adc_count-25;
switch(adc_count)
{
case 1:b6=1;
break;
case 2:b6=3;
break;
case 3:b6=7;
break;
case 4:b6=15;
break;
case 5:b6=31;
break;
}
}
if(adc_count>30 & adc_count<=35)//If the div > 30 and <= 35
{
b1=31;
b2=31;
b3=31;
b4=31;
b5=31;
b6=31;
adc_count=adc_count-30;
switch(adc_count)
{
case 1:b7=1;
break;
case 2:b7=3;
break;
case 3:b7=7;
break;
case 4:b7=15;
break;
case 5:b7=31;
break;
}
}
draw(b1,b2,b3,b4,b5,b6,b7); //invoking method draw()
}
void ftoi(float value) //creating method ftoi() to separate each digit
{
int vr2;
long int vr3;
vr2=value;
vr=value*10;
vr3=10;
vr3=vr3*vr2;
vr=vr-vr3;
volt_dec=vr%10;
vr/=10;
volt_ent=vr2%10;
vr2/=10;
}
void period(void) //creating method period() to display a dot in the matrix
{
select_led(3,1);
}
void integer_number(int num_ent)//creating method integer_number() to display the whole digi in the matrix
{
number(num_ent);
for( i=0;i<=2;i++)
{
select_led(i,c2[i]);
}
}
void decimal_number(int num_deci)//method decimal_nubmer() to display decimal digit
{
number(num_deci);
j=0;
for( i=4;i<=6;i++)
{
select_led(i,c2[j]);
j++;
}
}
void number(int num) //method number() is a library containing the figures for each number
{
switch(num)
{
case 0:
c2[0]=31;
c2[1]=17;
c2[2]=31;
break;
case 1:
c2[0]=9;
c2[1]=31;
c2[2]=1;
break;
case 2:
c2[0]=23;
c2[1]=21;
c2[2]=29;
break;
case 3:
c2[0]=21;
c2[1]=21;
c2[2]=31;
break;
case 4:
c2[0]=28;
c2[1]=4;
c2[2]=31;
break;
case 5:
c2[0]=29;
c2[1]=21;
c2[2]=23;
break;
case 6:
c2[0]=31;
c2[1]=21;
c2[2]=23;
break;
case 7:
c2[0]=16;
c2[1]=20;
c2[2]=31;
break;
case 8:
c2[0]=31;
c2[1]=21;
c2[2]=31;
break;
case 9:
c2[0]=29;
c2[1]=21;
c2[2]=31;
break;
}
}
void select_led(int f,int c) //method to select which LEDs to turn on in the matrix with a row and a column
{
switch(f)
{
case 0:P1OUT|=BIT0;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT0;
break;
case 1:P1OUT|=BIT1;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT1;
break;
case 2:P1OUT|=BIT2;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT2;
break;
case 3:P1OUT|=BIT4;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT4;
break;
case 4:P1OUT|=BIT5;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT5;
break;
case 5:P1OUT|=BIT6;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT6;
break;
case 6:P1OUT|=BIT7;
P2OUT&=~c;
__delay_cycles(1500);
P2OUT=63;
P1OUT &=~BIT7;
break;
}
}
void draw(int a1,int a2,int a3,int a4,int a5,int a6,int a7) //method to draw any figure by giving the decimal weight to each row
{
c2[0]=a1;
c2[1]=a2;
c2[2]=a3;
c2[3]=a4;
c2[4]=a5;
c2[5]=a6;
c2[6]=a7;
for( i=0;i<=6;i++)
{
select_led(i,c2[i]);
}
}
void voltimeter(void) //creating method voltimeter()
{
BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ;
BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1MHz
P1SEL |= BIT3; // ADC input pin P1.3
ConfigureAdc(); // ADC set-up function call
__enable_interrupt(); // Enable interrupts.
voltage=0;
ADC_value=0;
__delay_cycles(10000); // Wait for ADC Ref to settle
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
__bis_SR_register(CPUOFF + GIE); // Low Power Mode 0 with interrupts enabled
ADC_value = ADC10MEM; // Assigns the value held in ADC10MEM to the integer called ADC_value
}
#pragma vector=ADC10_VECTOR // ADC10 interrupt service routine
__interrupt void ADC10_ISR (void)
{
__bic_SR_register_on_exit(CPUOFF); // Return to active mode }
}
// Function containing ADC set-up
void ConfigureAdc(void) //configuring ADC
{
ADC10CTL1 = INCH_3 + ADC10DIV_3 ; // Channel 3, ADC10CLK/3
ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; // Vcc & Vss as references, Sample and hold for 64 Clock cycles, ADC on, ADC interrupt enable
ADC10AE0 |= BIT3; // ADC input enable P1.3
}