Hi,
I am working in a project involving a CC430F6137.
Basically the cc430 converts 1, 2, 3 or 4 signals (software selectable) and transmits them through the RF module to another device connected to a computer.
I want to set up the adc depending on an "adc_Combo" (a variable) and start the conversions later. The problem i am having is that it the adc is not interrumpting.
Any idea of whats going on??
I leave you here the main source file and the adc source file .
Gerardo
//ADC_A.c
#include "NeSiA_Remoto.h"
extern char TxBuffer0[PACKET_LEN];
extern char TxBuffer1[PACKET_LEN];
extern unsigned char UseTxBuff;
extern unsigned char converted;
unsigned char aux_adc0 = 0;
unsigned char aux_adc1 = 0;
unsigned char aux_adc2 = 0;
unsigned char aux_adc3 = 0;
/**
Función que inicializa el ADC en modo "repeat-single-channel" sobre 1
canal a 32 ksps, tomando 2,5V como Vref+. */
void InitAdc(unsigned char modo_func)
{
/* Hay 5 modos de funcionamiento posibles que se listan a continuación:
Modo 1 - 1 ch, freq muestreo 24,649 ksps
Modo 2 - 2 ch, freq muestreo 11,972 ksps
Modo 3 - 3 ch, freq muestreo 8,3 ksps
Modo 4 - 4 ch, freq muestreo 6,4 ksps
Modo 5 - 4 ch, freq muestreo 530 ksps
*/
/* Initialize REF module */
// Enable 2.5V shared reference, disable temperature sensor to save power
REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF;
/* Initialize ADC12_A */
ADC12CTL0 = ADC12ON+ADC12MSC; // Turn on ADC12, set sampling time
// set multiple sample conversion
switch (modo_func)
{
case 1:
// Enable A/D channel A0
P2SEL |= 0x01;
ADC12CTL0 = ADC12SHT0_2;
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2+ADC12DIV_6; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss,
ADC12IE = 0x01; // Enable ADC12IFG.0
break;
case 2:
// Enable A/D channels A0 & A1
P2SEL |= 0x03;
ADC12CTL0 = ADC12SHT0_4;
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3+ADC12DIV_4; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL1 = ADC12SREF_1+ ADC12INCH_1; // Vr+=Vref+ and Vr-=AVss
ADC12IE = 0x02; // Enable ADC12IFG.1
break;
case 3:
// Enable A/D channels A0, A1 & A2
P2SEL |= 0x07;
ADC12CTL0 = ADC12SHT0_5;
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3+ADC12DIV_4; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL1 = ADC12SREF_1+ ADC12INCH_1; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL2 = ADC12SREF_1+ ADC12INCH_2; // Vr+=Vref+ and Vr-=AVss
ADC12IE = 0x04; // Enable ADC12IFG.2
break;
case 4:
// Enable A/D channels A0, A1, A2 & A3
P2SEL |= 0x0F;
ADC12CTL0 = ADC12SHT0_6;
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3+ADC12DIV_4; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL1 = ADC12SREF_1+ ADC12INCH_1; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL2 = ADC12SREF_1+ ADC12INCH_2; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL3 = ADC12SREF_1+ ADC12INCH_3; // Vr+=Vref+ and Vr-=AVss
ADC12IE = 0x08; // Enable ADC12IFG.2
break;
case 5:
// Enable A/D channels A0, A1, A2 & A3
P2SEL |= 0x0F;
ADC12CTL0 = ADC12SHT0_12;
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3+ADC12DIV_7; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL1 = ADC12SREF_1+ ADC12INCH_1; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL2 = ADC12SREF_1+ ADC12INCH_2; // Vr+=Vref+ and Vr-=AVss
ADC12MCTL3 = ADC12SREF_1+ ADC12INCH_3; // Vr+=Vref+ and Vr-=AVss
ADC12IE = 0x08; // Enable ADC12IFG.2
break;
}
ADC12CTL2 = ADC12RES_0; // 8bits resolution
}
/**
ISR del ADC, copia el dato adquirido a AuxBuffer[] y al adquirir 60 muestras
consecutivas dispara la copia por DMA a TxBuffer (buffer usado para Tx).
*/
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
// static unsigned char index = 0;
static unsigned char index_b0 = 0;
static unsigned char index_b1 = 0;
switch(__even_in_range(ADC12IV,34))
{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: // Vector 6: ADC12IFG0
if(UseTxBuff){
TxBuffer0[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
if (index_b0 == (PACKET_LEN))
{
index_b0 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=0;
aux_adc0 = 0;
aux_adc0 = ADC12MEM0;
}
}
else{
TxBuffer1[index_b1++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
if (index_b1 == (PACKET_LEN))
{
index_b1 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=1;
aux_adc0 = ADC12MEM0;
}
}
__bic_SR_register_on_exit(LPM3_bits); // Exit active CPU
case 8: // Vector 8: ADC12IFG1
if(UseTxBuff){
TxBuffer0[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer0[index_b0++] = ADC12MEM1 - aux_adc1;
aux_adc1 = ADC12MEM1;
if (index_b0 == (PACKET_LEN))
{
index_b0 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=0;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
}
}
else{
TxBuffer1[index_b1++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer1[index_b1++] = ADC12MEM1 - aux_adc1;
aux_adc1 = ADC12MEM1;
if (index_b1 == (PACKET_LEN))
{
index_b1 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=1;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
}
}
__bic_SR_register_on_exit(LPM3_bits); // Exit active CPU
case 10: // Vector 10: ADC12IFG2
if(UseTxBuff){
TxBuffer0[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer0[index_b0++] = ADC12MEM1 - aux_adc1; // Move results
aux_adc1 = ADC12MEM1;
TxBuffer0[index_b0++] = ADC12MEM2 - aux_adc2; // Move results
aux_adc2 = ADC12MEM2;
if (index_b0 == (PACKET_LEN))
{
index_b0 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=0;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
aux_adc2 = ADC12MEM2;
}
}
else{
TxBuffer1[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer1[index_b0++] = ADC12MEM1 - aux_adc1; // Move results
aux_adc1 = ADC12MEM1;
TxBuffer1[index_b0++] = ADC12MEM2 - aux_adc2; // Move results
aux_adc2 = ADC12MEM2;
if (index_b1 == (PACKET_LEN))
{
index_b1 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=1;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
aux_adc2 = ADC12MEM2;
}
}
__bic_SR_register_on_exit(LPM3_bits); // Exit active CPU
case 12: // Vector 12: ADC12IFG3
if(UseTxBuff){
TxBuffer0[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer0[index_b0++] = ADC12MEM1 - aux_adc1; // Move results
aux_adc1 = ADC12MEM1;
TxBuffer0[index_b0++] = ADC12MEM2 - aux_adc2; // Move results
aux_adc2 = ADC12MEM2;
TxBuffer0[index_b0++] = ADC12MEM3 - aux_adc3; // Move results
aux_adc3 = ADC12MEM3;
if (index_b0 == (PACKET_LEN))
{
index_b0 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=0;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
aux_adc2 = ADC12MEM2;
aux_adc3 = ADC12MEM3;
}
}
else{
TxBuffer1[index_b0++] = ADC12MEM0 - aux_adc0; // Move results
aux_adc0 = ADC12MEM0;
TxBuffer1[index_b0++] = ADC12MEM1 - aux_adc1; // Move results
aux_adc1 = ADC12MEM1;
TxBuffer1[index_b0++] = ADC12MEM2 - aux_adc2; // Move results
aux_adc2 = ADC12MEM2;
TxBuffer1[index_b0++] = ADC12MEM3 - aux_adc3; // Move results
aux_adc3 = ADC12MEM3;
if (index_b1 == (PACKET_LEN))
{
index_b1 = 0; // Reset the index; Set Breakpoint here
converted =1; // Se convirtieron 60 paquetes
UseTxBuff=1;
aux_adc0 = ADC12MEM0;
aux_adc1 = ADC12MEM1;
aux_adc2 = ADC12MEM2;
aux_adc3 = ADC12MEM3;
}
}
__bic_SR_register_on_exit(LPM3_bits); // Exit active CPU
case 14: break; // Vector 14: ADC12IFG4
case 16: break; // Vector 16: ADC12IFG5
case 18: break; // Vector 18: ADC12IFG6
case 20: break; // Vector 20: ADC12IFG7
case 22: break; // Vector 22: ADC12IFG8
case 24: break; // Vector 24: ADC12IFG9
case 26: break; // Vector 26: ADC12IFG10
case 28: break; // Vector 28: ADC12IFG11
case 30: break; // Vector 30: ADC12IFG12
case 32: break; // Vector 32: ADC12IFG13
case 34: break; // Vector 34: ADC12IFG14
default: break;
}
}
-----------------------------
//MAIN.c
#include "NeSiA_Remoto.h"
#include "spi.h"
#define PKT_a_transmitir (10000)
/* Parámetros de configuración, deberán guardarse en Flash, y quedar guardados
después de un reset o un OFF */
unsigned int filter_freq = 5000;
unsigned long int gain0 = 100000; // Ganancia total del sistema [2800 - 257000]
unsigned long int gain1 = 10000; // Ganancia total del sistema [2800 - 257000]
unsigned long int gain2 = 10000; // Ganancia total del sistema [2800 - 257000]
unsigned long int gain3 = 10000; // Ganancia total del sistema [2800 - 257000]
unsigned char adc_combo = 1;
unsigned int tiempo_prueba = 0; // Tiempo de la prueba en minutos
unsigned char buff_pruebas[] = "Esto es una prueba, llega bien? Dale que queremos terminar.";
/*------------------------------------- */
// Contador de Interrupciones para el tiempo de la prueba
unsigned long int t_prueba_secs = 60;
// ---------------------------------------------------
unsigned char converted = 0; // Flag para indicar que hay 60 datos convertidos
unsigned char transmitting = 0; // Flag que indica si se está trasmitiendo
unsigned char TxBuffer0[PACKET_LEN]; // Buffer de Transmisión 0
unsigned char TxBuffer1[PACKET_LEN]; // Buffer de Transmisión 1
unsigned char PKT[PACKET_LEN] = {
0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE ,0xAD,
0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD,
0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD, 0xDE, 0xAD};
// Bandera que indica modo de funcionamiento mode_conf
unsigned char mode_conf = 0;
unsigned long int PKT_enviados = 0;
// Bandera de selección de buffer para Tx, el ADC escribe en el otro
unsigned char UseTxBuff = 0;
extern unsigned int LecturaSpi;
void main( void ){
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
// Enable 32kHz ACLK
// Configure CPU clock for 12MHz
InitUCS();
// Increase PMMCOREV level to 2 for proper radio operation
SetVCore(2);
//Inicialización de la Radio, Adc y Leds
InitButtonLeds();
ResetRadioCore();
InitRadio();
InitSpi();
__bis_SR_register( GIE );
EnableWriteSpi(0);
EnableWriteSpi(1);
EnableWriteSpi(2);
EnableWriteSpi(3);
// Seteo con parámetros guardados
ConfigureAll();
EnterModeAcq(); // Comienzo a adquirir
//Loop principal del sistema, se mantiene verificando si tiene datos convertidos y si esta transmitiendo.
while (1)
{
// modo configuración
if (mode_conf){
__bis_SR_register( LPM3_bits + GIE );
__no_operation(); // Para evitar el bug de program counter corrumption por entrar en LPM3 (errata CPU24,CPU39)
// cada x ms mando un beacon
}else
{
//__bis_SR_register( LPM3_bits + GIE );
__bis_SR_register( LPM3_bits + GIE );
__no_operation(); // Para evitar el bug de program counter corrumption por entrar en LPM3 (errata CPU24,CPU39)
//
if(converted){
while(transmitting);
converted = 0;
if(UseTxBuff){
//Transmit( (unsigned char*)TxBuffer1, sizeof TxBuffer1);
Transmit( (unsigned char*)buff_pruebas, sizeof buff_pruebas);
}
else {
//Transmit( (unsigned char*)TxBuffer0, sizeof TxBuffer0);
Transmit( (unsigned char*)buff_pruebas, sizeof buff_pruebas);
}
transmitting = 1;
PKT_enviados++;
}
}
}
}
// Función que entra en modo configuración
void EnterModeConf(void){
int i=0;
while (i<12) {
P3OUT ^= BIT6;
// Toglea LED cada 250 milisegundos
__delay_cycles(3000000);
i++;
}
TimeInterrupt(2);
ReceiveOn();
mode_conf = 1;
P3OUT != BIT6;
}
// Función que entra en modo adquisición
void EnterModeAcq(void){
// Transmito un ACK con la configuración actual
SendConfig();
// Saco a la radio de modo recepción
ReceiveOff();
// Prendo LED por 3 segundos
P3OUT = BIT6;
__delay_cycles(36000000);
P3OUT = ~BIT6;
mode_conf = 0;
ADC12CTL0 |= ADC12ENC; // Enable conversions
ADC12CTL0 |= ADC12SC; // Start conversion
TA0CCR0 = MC_1;
t_prueba_secs = tiempo_prueba * 60;
}
//Funcion que inicializa el Unified Clock System, del cual se generan los
//relojes de referencia del sistema: ACLK, MCLK y SMCLK
void InitUCS(void){
// Enable 32kHz ACLK
P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1
UCSCTL6 &= ~XT1OFF; // XT1 On, Highest drive strength
UCSCTL6 |= XCAP_3; // Internal load cap
UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference
UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV;
// ---------------------------------------------------------------------
// Configure CPU clock for 12MHz
_BIS_SR(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_5; // Select suitable range
UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier
_BIC_SR(SCG0); // Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle
__delay_cycles(250000);//Gerardo: No estamos usando el clock a 12MHz en lugar de 8MHz?
// De ser asi deberiamos usar aca 375000 en lugar de 250000
// Loop until XT1 & DCO stabilizes,
// use do-while to insure that body is executed at least once
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
SFRIFG1 &= ~OFIFG; // Clear fault flags
} while ((SFRIFG1 & OFIFG));
}
/** Esta función inicializa el uso de los LEDs y botones.*/
void InitButtonLeds(void){
// Set up the button as interruptible
P1DIR &= ~BIT7;
P1REN |= BIT7;
P1IES &= BIT7;
P1IFG = 0;
P1OUT |= BIT7;
P1IE |= BIT7;
// Initialize Port J
PJOUT = 0x00;
PJDIR = 0xFF;
// Set up LEDs
// P1OUT &= ~BIT0;
// P1DIR |= BIT0;
P3OUT &= ~BIT6;
P3DIR |= BIT6;
}
//Funcion que manega la configuración del reloj para fec. de corte del MAX7414
//La onda cuadrada se genera en el Timer A con SMCLK como fuente, se cuenta hasta TA1CCR0 y togglea la salida en P2.6
void CLKFilter(unsigned int freq){
// freq es la frecuencia de corte del filtro MAX7414.
// La onda cuadrada a salir por P2.6 es 100*freq
TA0CCR0 = 120000/(freq*2); //Gerardo, aca esta hardcodeada la frec del micro dividido 100?
TA0CCR1 = 120000/(freq*2); //Gerardo, aca esta hardcodeada la frec del micro dividido 100?
TA0CCTL1 = OUTMOD_4;
TA0CTL = TASSEL__SMCLK + MC_1 + TACLR;
P2SEL |= BIT6; // P2.6 (TA1 out)
P2DIR |= BIT6; // P2.6 TA1CCR1 output
}
// Función que configura todos los parámetros
void ConfigureAll(void){
WriteSpi(gain0,0);
InitAdc(adc_combo);
WriteSpi(gain1,1);
CLKFilter(filter_freq);
WriteSpi(gain2,2);
TimeInterrupt();
WriteSpi(gain3,3);
}
// Función que envía la configuración al móduo base
void SendConfig(){
// ACK
PKT[0] = 0xAC;
// adc_combo
PKT[3] = adc_combo;
// filter_freq
PKT[6] = (filter_freq && 0xFF00) >> 8;
PKT[7] = filter_freq && 0xFF;
// tiempo_prueba
PKT[10] = (tiempo_prueba && 0xFF00) >> 8;
PKT[11] = tiempo_prueba && 0xFF;
// gain 0
PKT[14] = (gain0 && 0xFF000000) >> 24;
PKT[15] = (gain0 && 0xFF0000) >> 16;
PKT[16] = (gain0 && 0xFF00) >> 8;
PKT[17] = gain0 && 0xFF;
// gain 1
PKT[20] = (gain1 && 0xFF000000) >> 24;
PKT[21] = (gain1 && 0xFF0000) >> 16;
PKT[22] = (gain1 && 0xFF00) >> 8;
PKT[23] = gain1 && 0xFF;
// gain 2
PKT[30] = (gain0 && 0xFF000000) >> 24;
PKT[31] = (gain0 && 0xFF0000) >> 16;
PKT[32] = (gain0 && 0xFF00) >> 8;
PKT[33] = gain0 && 0xFF;
// gain 3
PKT[40] = (gain1 && 0xFF000000) >> 24;
PKT[41] = (gain1 && 0xFF0000) >> 16;
PKT[42] = (gain1 && 0xFF00) >> 8;
PKT[43] = gain1 && 0xFF;
Transmit( (unsigned char*)PKT, sizeof PKT);
}
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void){
switch(__even_in_range(P1IV, 16))
{
case 0: break;
case 2: break; // P1.0 IFG
case 4: break; // P1.1 IFG
case 6: break; // P1.2 IFG
case 8: break; // P1.3 IFG
case 10: break; // P1.4 IFG
case 12: break; // P1.5 IFG
case 14: break; // P1.6 IFG
case 16: // P1.7 IFG
P1IE = 0; // Debounce by disabling buttons
if(mode_conf){
EnterModeAcq();
}
else{
EnterModeConf();
}
P1IE |= BIT7;
break;
}
}
void TimeInterrupt(){
// RTC en modo timer, interrumpe cada 1 segundo
// Setup RTC Timer
RTCCTL01 = RTCTEVIE + RTCSSEL_2 + RTCTEV_0; // Counter Mode, RTC1PS, 8-bit ovf
// overflow interrupt enable
RTCPS0CTL = RT0PSDIV_2; // ACLK, /8, start timer
RTCPS1CTL = RT1SSEL_2 + RT1PSDIV_3; // out from RT0PS, /16, start timer
}
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
{
switch(__even_in_range(RTCIV,16))
{
case 0: break; // No interrupts
case 2: break; // RTCRDYIFG
case 4: // RTCEVIFG
if(mode_conf){
// send_beacon
while(transmitting);
sendBeacon();
P3OUT ^= BIT6;
}
else {
if (tiempo_prueba > 0) {
if (t_prueba_secs > 0) {
t_prueba_secs--;
}
else {
EnterModeConf();
P3OUT ^= BIT6;
}
}
}
break;
case 6: break; // RTCAIFG
case 8: break; // RT0PSIFG
case 10: break; // RT1PSIFG
case 12: break; // Reserved
case 14: break; // Reserved
case 16: break; // Reserved
default: break;
}
}
void sendBeacon(void){
PKT[0]=0xBE;
PKT[1]=0xAC;
Transmit( (unsigned char*)PKT, sizeof PKT);
}