Skip to content

Instantly share code, notes, and snippets.

@Guitlle
Created April 18, 2013 22:48
Show Gist options
  • Save Guitlle/5416848 to your computer and use it in GitHub Desktop.
Save Guitlle/5416848 to your computer and use it in GitHub Desktop.
Osciloscopio para la launchpad MSP430 con el chip msp430g2553. Tiene 8 velocidades y funciona vía el puerto seria (UART) para que funcione deben voltear los JUMPERs que dicen TX y RX (hardware uart). A 9600 baudios por segundo, se le envía un caracter y la launchpad responde con 200 datos obtenidos mediante el ADC . Requiere que el cristal que t…
#include "msp430g2553.h"
#include "stdbool.h"
#define LED BIT6
#define RXD BIT1
#define TXD BIT2
unsigned int i; // for loop variable
volatile unsigned char rx_flag = 0;
volatile unsigned char tx_flag = 0;
volatile unsigned char rx_char = 0;
volatile unsigned char tx_char = 0;
void Set_DCO();
void print(char *);
void print_newline();
void print_hexb(register unsigned char);
void print_hexw(register unsigned int);
unsigned char ugetc();
void uputc(register unsigned char c);
void print();
// ASCII values for the commands
#define TEST 0x31
#define CALIB 0x32
#define M_A3 0x33
#define M_TEMP 0x34
#define M_VCC 0x35
#define BURST1 97
#define BURST2 98
#define BURST3 99
#define BURST4 100
#define BURST5 101
#define BURST6 102
#define BURST7 103
#define IDLE 0x00
#define AWAKE_ME 0x01
bool ADCDone; // ADC Done flag
unsigned int ADCValue; // Measured ADC Value
unsigned char datos[400], Estado;
/**
* Reads ADC 'chan' once using AVCC as the reference.
**/
void Single_Measure(unsigned int chan)
{
ADC10CTL0 &= ~ENC; // Disable ADC
ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE; // 64 clock ticks, ADC On, enable ADC interrupt
ADC10CTL1 = ADC10SSEL_3 + chan; // // Set 'chan', SMCLK
ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion
}
/**
* Reads ADC 'chan' once using an internal reference, 'ref' determines if the
* 2.5V or 1.5V reference is used.
**/
void Single_Measure_REF(unsigned int chan, unsigned int ref)
{
ADC10CTL0 &= ~ENC; // Disable ADC
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ref + ADC10IE; // Use reference,
// 64 clock ticks, internal reference on
// ADC On, enable ADC interrupt, Internal = 'ref'
ADC10CTL1 = ADC10SSEL_3 + chan; // Set 'chan', SMCLK
__delay_cycles (400); // Delay to allow Ref to settle
ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion
}
void loop(){
if(ADCDone) // If the ADC is done with a measurement
{
ADCDone = false; // Clear flag
print_hexw(ADCValue);
print_newline();
}
ugetc();
switch(rx_char) // Switch depending on command value received
{
case CALIB:
print ("BCSCTL1 ");print_hexb(BCSCTL1);print_newline();
print ("DCOCTL ");print_hexb(DCOCTL);
print_newline();break;
case TEST:
print("#TEST LED\n\r");
P1OUT ^= BIT6; // toggle led
break;
case M_A3:
Single_Measure(INCH_0); // Reads A0 only once
break;
case M_TEMP:
Single_Measure_REF(INCH_10, 0); // Reads the temperature sensor once
break;
case M_VCC:
Single_Measure_REF(INCH_11, REF2_5V); // Reads VCC once (VCC/2 internally)
break;
case BURST1:
case BURST2:
case BURST3:
case BURST4:
case BURST5:
case BURST6:
case BURST7:
ADC10CTL0 = ADC10SHT_1 + MSC + ADC10ON + ADC10IE ;
print("#Transmitiendo BURST");
switch (rx_char){
case BURST1:
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10SSEL_3;
print(" DIV0 ");
break;
case BURST2:
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_1 + ADC10SSEL_3;
print(" DIV1 ");
break;
case BURST3:
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_3 + ADC10SSEL_3 ;
print(" DIV3 ");
break;
case BURST4:
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_7 + ADC10SSEL_3;
print(" DIV7 ");
break;
case BURST5:
ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE ;
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_7 + ADC10SSEL_3;
print(" DIV7 ");
break;
case BURST6:
ADC10CTL0 = ADC10SHT_3 + MSC + ADC10ON + ADC10IE ;
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_7+ADC10SSEL_3;
print(" DIV7 ");
break;
case BURST7:
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10SSEL_1; // AMCLK
print(" DIV8 ");
break;
}
print_newline();
// ADC10ON, interrupt enabl
ADC10DTC1 = 200; // 225 conversions
ADC10AE0 |= BIT0; // P1.0 ADC option select
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10SA = (unsigned int) datos; // Data buffer start
P1OUT |= BIT6; // Set GREEN LED on
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
Estado = AWAKE_ME;
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
P1OUT &= ~BIT6; // Clear GREEN LED off
for (i=0;i<400;i+=2){
print_hexb(datos[i+1]);
print_hexb(datos[i]);
print_newline();
}
break;
default:;
}
}
/**
* ADC interrupt routine. Pulls CPU out of sleep mode
**/
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
if (Estado == AWAKE_ME){
Estado = IDLE;
__bic_SR_register_on_exit(CPUOFF); // Enable CPU
return;
}
ADCValue = ADC10MEM; // Saves measured value.
ADCDone = true; // Sets flag for main loop.
__bic_SR_register_on_exit(CPUOFF); // Enable CPU so the main while loop continues
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
Set_DCO();
//***************** INIT USCI UART
P1DIR |= LED;
P1OUT |= LED;
//BCSCTL2 |= BIT1; // SMCLK = DCOCLK / 2
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0x80; // 9600
UCA0BR1 = 0x1; // 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(GIE); // Enter LPM0, interrupts enabled
while (1){
loop();
}
}
unsigned char ugetc() //Waits for a valid char from the UART
{
while (rx_flag == 0); //Wait for rx_flag to be set
rx_flag = 0; //ACK rx_flag
return rx_char;
}
void uputc(register unsigned char c)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = c; // TX -> c
}
void print(char *str) //Sends a String to the UART.
{
while(*str) uputc(*str++); //Advance though string till end
return;
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
rx_char = UCA0RXBUF;
rx_flag = 1;
}
//--------------------------------------------------------------------------
void Set_DCO() // Set DCO to 3.6864 MHz
//--------------------------------------------------------------------------
{
#define Delta 3686400/4096 // 3686400
BCSCTL3 = (BCSCTL3 & ~XCAP_3) | XCAP_0;
__delay_cycles(0xFFFF);
unsigned int Compare, Oldcapture = 0;
BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8
TACCTL0 = CM_1 | CCIS_1 | CAP; // CAP, ACLK
TACTL = TASSEL_2 | MC_2 | TACLR; // SMCLK, continuous mode, clear
while (1) {
while (!(CCIFG & TACCTL0)); // Wait until capture occurred
TACCTL0 &= ~CCIFG; // Capture occurred, clear flag
Compare = TACCR0; // Get current captured SMCLK
Compare = Compare - Oldcapture; // SMCLK difference
Oldcapture = TACCR0; // Save current captured SMCLK
if (Delta == Compare) break; // If equal, leave "while(1)"
else if (Delta < Compare) {
DCOCTL--; // DCO is too fast, slow it down
if (DCOCTL == 0xFF) // Did DCO roll under?
if (BCSCTL1 & 0x0f)
BCSCTL1--; // Select lower RSEL
}
else {
DCOCTL++; // DCO is too slow, speed it up
if (DCOCTL == 0x00) // Did DCO roll over?
if ((BCSCTL1 & 0x0f) != 0x0f)
BCSCTL1++; // Select higher RSEL
}
}
TACCTL0 = 0; // Stop TACCR0
TACTL = 0; // Stop Timer_A
BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK
__delay_cycles(0x4000);
}
void print_newline()
{
uputc('\n');
uputc('\r');
}
void print_hexb(register unsigned char c)
{
static const unsigned char hextbl[]="0123456789ABCDEF";
uputc(hextbl[c >> 4]);
uputc(hextbl[c& 0x0F]);
}
void print_hexw(register unsigned int c)
{
static const unsigned char hextbl[]="0123456789ABCDEF";
uputc(hextbl[c >> 12]);
uputc(hextbl[(c >> 8)& 0x000F]);
uputc(hextbl[(c >> 4)& 0x000F]);
uputc(hextbl[c & 0x000F]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment