Forums

Set up output pin 2.5 as a square wave.

Started by rnkruppa 2 years ago4 replieslatest reply 2 years ago75 views
Hi, all I am new here, and have been learning C coding. I am currently trying to set up a temperature sensor to read the temperature in the room, and turn the blue light on if it exceeds, or falls below it. I also want a buzzer to should when the temp reaches the certain point. currently I am using a program called terminal.exe to display the temperature. Currently I am displaying temp, and able to turn on the blue light. However I want to configure a timer as a output to a pin on my MSP430 to hook a buzzer up to. I just need the voltage to change to make the buzzer sound. Thus I need a square wave as the output. But I don't know how to set up the timer as the output to pin 2.5, if you guys have any idea please let me know. Here is my code currently.


#include <msp430.h>
#include "serial_msp.h"
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
#include "HAL_board.h"
#include "HAL_LCD.h"
int r;
int upndown, count, increment;
void print(char *text)
{
unsigned int i=0;
while(text[i] !='\0')
{
while(!(IFG2&UCA0TXIFG));
UCA0TXBUF=text[i]; //TX recieved Char+1
i++;
}
}

int main(void)
{
P2DIR|=0xa0; //0x20 is blue light 0xa0 is P5 and 7



WDTCTL = WDTPW + WDTHOLD; // stop WDT

DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
P1DIR |= BIT4;
P1OUT &= ~BIT4;

P1SEL = BIT1 + BIT2; // Select UART as the pin function
P1SEL2 = BIT1 + BIT2;

UCA0CTL1 |= UCSWRST; // Disable UART module for configuration

UCA0CTL0 = 0x00; // No parity, LSB first, 8-bit data, 1 stop bit, UART, Asynchronous
UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK source, keep in reset state
UCA0BR0 = 104; // 9600 Baud rate - Assumes 1 MHz clock
UCA0BR1 = 0; // 9600 Baud rate - Assumes 1 MHz clock
UCA0MCTL = 0x02; // 2nd Stage modulation = 1, Oversampling off
UCA0CTL1 &= ~UCSWRST; // Enable UART module


// ADC configuration,V+ref=3V,V-ref=0V,Channel=A0
ADC10CTL0 = ADC10SHT_0 +ADC10ON + ADC10IE; // Vref Vr+=3v,Vr-=VSS,
// S&Htime = 4 X ADCCLK,ADC10 on,ADC interrupts enabled
ADC10CTL1 = ADC10DIV_0+ ADC10SSEL_0+CONSEQ_0; // INCH =0000->A0,ADCCLK src = ADC10CLK,
// ADCCLK/8,Single Channel Single Conversion
ADC10AE0 = INCH_0; // channel A0

ADC10CTL0 |= ENC + ADC10SC; // Start Conversion

_BIS_SR(LPM0_bits +GIE); // Go to LPM0,interrupts enabled


while(1)
{ADC10CTL0|= ENC+ADC10SC;
unsigned int adcValue=ADC10MEM;
unsigned long voltageValue;
unsigned long F;
unsigned long Fa;
voltageValue= (adcValue/10);
F= ((voltageValue*9)/5);
Fa= (F+32);
serial_string("The Voltage is:");
serial_number(adcValue);
serial_string("mV");
print("\r\n");
serial_string("the Temp is: ");
serial_number(voltageValue);
serial_string("Celsius");
print("\r\n");
serial_number(Fa);
serial_string("Fahrenheit");
print("\r\n");
if (ADC10MEM < 900)
{P1OUT &= ~BIT0;
}
else
{P1OUT |= BIT0;}

if(Fa>=69){P2OUT =0x20; }//*/
else if(Fa<69){P2OUT=~0x20;}

}
}




#pragma vector = ADC10_VECTOR
__interrupt void adc10_interrupt(void)

{
__bic_SR_register_on_exit(CPUOFF);

}
[ - ]
Reply by mr_banditApril 23, 2019

A standard method is to setup the timer to call an ISR function when the timer hits a count. (Hint: you can setup a timer as a downcounter, so the ISR is called when the count == 0. Often you can also set a max count && upcount && the ISR is called when it hits the high count.)

A common way to know your ISR is operating is to set a pin high when you enter && set it low before the ISR exits. This (1) proves the ISR is entered, and (2) the time in the ISR. (In general, you should be in an ISR as short as possible).

Set the timer count to what you need for your square wave frequency.

(I assume you have access to an oscope.)

So: setup a timer ISR. Within the ISR, toggle the pin you want to create the square wave. Make sure only the ISR knows about the flag:

timer_ISR

{

static int flag = 0;

if( flag ) { set_pin_low; flag = 0; }

else {set_pin_high; flag = 1; }

}

Does this make sense? Hope this helps.

[ - ]
Reply by rnkruppaApril 23, 2019
thanks for the reply however my knowledge of code is extremely basic at this point. I don't actually know what you mean by ISR. Also I currently do not have access to a Oscope. 
[ - ]
Reply by mr_banditApril 24, 2019

You already have an ISR defined:

#pragma vector = ADC10_VECTOR
__interrupt void adc10_interrupt(void)

{
__bic_SR_register_on_exit(CPUOFF);

}

Scope: look at rygol DS1054Z  under $400 50MHz (but i will not tell you about the free tool you can find on the net to change one byte of EEPROM to turn it into a 100 MHz scope.) A lot of makerspaces have these n their electronic labs. Solid, easy to use.

This scope is at least 90% (or more) of the HP scope I bought 10+ years ago for $2400. I am considering getting one of these as my "beater scope". (and pop the $50..60 at harbor freight or wherever for the hard-shell case with the foam inside as a carry case. Makes it very easy to take with you..)

https://www.rigolna.com/products/digital-oscilloscopes/1000z/

If you are planning on doing embedded systems in the future, you really need a scope. Otherwise you are flying blind. And get one with 4 inputs - trust me... (I'm an engineer :^) As it is, with any complex design, you will wish you had one more than the scope provides.

[ - ]
Reply by bitkingApril 23, 2019

ISR is Interrupt Service Routine.

You can set the timers up to count down and when they hit zero you can have a section of code run (the ISR) to set the counter up again AND toggle your output pin. Meanwhile - your code can be doing whatever you want while it is waiting for the ISR. 

The computer you are reading this with has many Interrupt routines that runs every time you hit a key or move the mouse a tiny bit. 


Have you looked at this tutorial here on the ER site?

https://www.embeddedrelated.com/showarticle/182.ph...


Or you can go to the TI mothership here:

https://training.ti.com/getting-started-msp430-5xx...