This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
使用DMA通道0和1,设置中断使能,直接复制的官方例程中的DMA中断服务程序,应该是需要两个,DMA0的和DMA1的,官方例程只有一种,如何配置才能分别触发通道0和1的中断,进入中断服务程序,官方中断服务程序如下
//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
P1OUT ^= BIT0; // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE
break;
case 4: break; // DMA1IFG = DMA Channel 1
case 6: break; // DMA2IFG = DMA Channel 2
case 8: break; // DMA3IFG = DMA Channel 3
case 10: break; // DMA4IFG = DMA Channel 4
case 12: break; // DMA5IFG = DMA Channel 5
case 14: break; // DMA6IFG = DMA Channel 6
case 16: break; // DMA7IFG = DMA Channel 7
default: break;
}
}
#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
volatile unsigned int buf[512];
volatile int input[256];
//volatile unsigned int adc_result[512];
unsigned char ADC12_flag=0;
unsigned char DMA0flag=2;
unsigned char DMA1flag=0;
void GPIO_INIT(){
// Configure GPIOs to it's lowest power state
P1OUT = 0; // All P1.x reset
P1DIR = 0xFF; // All P1.x outputs
P2OUT = 0; // All P2.x reset
P2DIR = 0xFF; // All P2.x outputs
P3OUT = 0; // All P3.x reset
P3DIR = 0xFF; // All P3.x outputs
P4OUT = 0; // All P4.x reset
P4DIR = 0xFF; // All P4.x outputs
P5OUT = 0; // All P5.x reset
P5DIR = 0xFF; // All P5.x outputs
P6OUT = 0; // All P6.x reset
P6DIR = 0xFF; // All P6.x outputs
P7OUT = 0; // All P7.x reset
P7DIR = 0xFF; // All P7.x outputs
P8OUT = 0; // All P8.x reset
P8DIR = 0xFF; // All P8.x outputs
PJOUT = 0; // All PJ.x reset
PJDIR = 0xFFFF; // All PJ.x outputs
P1SEL0 |= BIT3; // configure P1.3/A3 for ADC function
P1SEL1 |= BIT3; //
P3DIR |= BIT4;
P3SEL1 |= BIT4; // Output MCLK
P3SEL0 |= BIT4;
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
}
void CLOCK_init(){
// Clock System Setup
CSCTL0_H = CSKEY_H; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
// Per Device Errata set divider to 4 before changing frequency to
// prevent out of spec operation from overshoot transient
CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata
CSCTL1 = DCOFSEL_6; // Set DCO to 8MHz
// Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
__delay_cycles(60);
CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers
CSCTL0_H = 0; // Lock CS Registers
}
void TIMER_init(){
// Configure Timer0_A3 to periodically trigger the ADC12 设置定时器周期
TA0CCR0 = 250; // PWM Period
TA0CCTL1 = OUTMOD_7; // TACCR1 set/reset
TA0CCR1 = 10; // TACCR1 PWM Duty Cycle
TA0CTL = TASSEL__SMCLK | MC__UP | TACLR; // ACLK, up mode
}
void DMA_init(){
// Configure DMA channel 0
__data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &ADC12MEM0);
// Source block address
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
// Destination single address
DMA0SZ =256; // Block size
// DMA0CTL &= ~DMAIFG; //清楚中断标志,防止未发生中断前已置位
DMA0CTL = DMADT_4 | DMASRCINCR_0 | DMADSTINCR_3 | DMAIE; // Rpt, inc
DMACTL0|= DMA0TSEL_26; //DMA触发源ADCIFG
DMA0CTL|= DMAEN; // Enable DMA0
/*Configure DMA channel 1*/
__data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &buf[0]);
__data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) &input);
DMA1SZ =256; // Block size
// DMA1CTL &= ~DMAIFG; //清楚中断标志,防止未发生中断前已置位
DMA1CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3 | DMAIE ; // Rpt, inc
DMA1CTL|= DMAEN; // Enable DMA0
}
void ADC12_init(){
ADC12CTL0 = ADC12SHT0_0 | ADC12ON; // Sampling time, S&H=4(4个采样保持AD时钟周期), ADC12 on开启AD
// Use TA0.1 to trigger, and repeated-single-channel 脉冲采样模式,触发源SAMPCON来自采样样本定时器,它的输入来自定时器TA0.1(数据手册) ,选择单通道重复转换模式,时钟源SMCLK
ADC12CTL1 = ADC12SHP | ADC12SHS_1 | ADC12CONSEQ_2 | ADC12SSEL_3;
// A1 ADC input select; Vref+ = AVCC 中断源选择,选择A1通道,序列未结束,参考电压默认没有设置
ADC12MCTL0 = ADC12INCH_3 | ADC12EOS;
ADC12CTL2 |= ADC12RES_2; //转换的位数12
// ADC12IER0 |= ADC12IE0; // Enable ADC interrupt 使能ADC12IFGO中断
ADC12IER2 |= ADC12TOVIE; //使能ADC转换时间溢出中断
ADC12IER2 |= ADC12OVIE; //使能MEM缓存存储器溢出中断位
ADC12CTL0 |= ADC12ENC ; // Start sampling/conversion 开启AD转换
__bis_SR_register(GIE); // Enter LPM0, enable interrupts
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
GPIO_INIT();
CLOCK_init();
TIMER_init();
DMA_init();
// __bis_SR_register(GIE); // 打开全局中断
/*
while(1){
P1OUT|= 0x01; // P1.0 = 1, LED on
DMA0CTL|= DMAREQ; // Trigger block transfer
}
*/
P1OUT |= BIT1; // P1.1 = 1
ADC12_init();
while(1){
switch(DMA0flag){
case 0:
DMA1CTL|= DMAREQ; // 软件触发DMA1转移数据
DMA0flag=2;
break;
case 1:
DMA1CTL|= DMAREQ; // 软件触发DMA1转移数据
DMA0flag=2;
break;
default :
break;
}
}
__no_operation();
return 0;
}
//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
switch(ADC12_flag){
case 0:
DMA0flag=0;
DMA0CTL&= ~DMAEN; // Enable DMA0
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[256]);
DMA0CTL|= DMAEN; // Enable DMA0
ADC12_flag=1;
break;
case 1:
DMA0flag=1;
DMA0CTL&= ~DMAEN; // Enable DMA0
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
DMA0CTL|= DMAEN; // Enable DMA0
ADC12_flag=0;
break;
default :
break;
}
break;
case 4:
DMA1flag=1;
break; // DMA1IFG = DMA Channel 1
/*
case 6: break; // DMA2IFG = DMA Channel 2
case 8: break; // DMA3IFG = DMA Channel 3
case 10: break; // DMA4IFG = DMA Channel 4
case 12: break; // DMA5IFG = DMA Channel 5
case 14: break; // DMA6IFG = DMA Channel 6
case 16: break; // DMA7IFG = DMA Channel 7
default: break;*/
}
}
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
switch(ADC12_flag){
case 0:
DMA0flag=0;
DMA0CTL&= ~DMAEN; // Enable DMA0
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[256]);
DMA0CTL|= DMAEN; // Enable DMA0
ADC12_flag=1;
break;
case 1:
DMA0flag=1;
DMA0CTL&= ~DMAEN; // Enable DMA0
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
DMA0CTL|= DMAEN; // Enable DMA0
ADC12_flag=0;
break;
default :
break;
}
这里有两个case0。case1在这里是不起作用的,这case后面只能是偶数。
/*
*
*
* ADC每采样转换不会进入中断,采样一次就通过DMA传输一次至指定缓存,DMA为ADCMEM寄存器中断标志触发,采用重复单地址传输模式,传完256个点后DMA的使能位会自动置1,同时触发中断标志DMAIFG,解决循环传数问题
*当通道0传输完成之后,通过DMA通道1将数据搬移至FFT运算的地址空间,此程序测试使用两个DMA通道能否触发各自中断
*/
#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
volatile unsigned int buf[512];
volatile int input[256];
//volatile unsigned int adc_result[512];
unsigned char flag=0;
unsigned char DMA0flag=0;
unsigned char DMA1flag=0;
void GPIO_INIT(){
// Configure GPIOs to it's lowest power state
P1OUT = 0; // All P1.x reset
P1DIR = 0xFF; // All P1.x outputs
P2OUT = 0; // All P2.x reset
P2DIR = 0xFF; // All P2.x outputs
P3OUT = 0; // All P3.x reset
P3DIR = 0xFF; // All P3.x outputs
P4OUT = 0; // All P4.x reset
P4DIR = 0xFF; // All P4.x outputs
P5OUT = 0; // All P5.x reset
P5DIR = 0xFF; // All P5.x outputs
P6OUT = 0; // All P6.x reset
P6DIR = 0xFF; // All P6.x outputs
P7OUT = 0; // All P7.x reset
P7DIR = 0xFF; // All P7.x outputs
P8OUT = 0; // All P8.x reset
P8DIR = 0xFF; // All P8.x outputs
PJOUT = 0; // All PJ.x reset
PJDIR = 0xFFFF; // All PJ.x outputs
P1SEL0 |= BIT3; // configure P1.3/A3 for ADC function
P1SEL1 |= BIT3; //
P3DIR |= BIT4;
P3SEL1 |= BIT4; // Output MCLK
P3SEL0 |= BIT4;
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
}
void CLOCK_init(){
// Clock System Setup
CSCTL0_H = CSKEY_H; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
// Per Device Errata set divider to 4 before changing frequency to
// prevent out of spec operation from overshoot transient
CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata
CSCTL1 = DCOFSEL_6; // Set DCO to 8MHz
// Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
__delay_cycles(60);
CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers
CSCTL0_H = 0; // Lock CS Registers
}
void TIMER_init(){
// Configure Timer0_A3 to periodically trigger the ADC12 设置定时器周期
TA0CCR0 = 250; // PWM Period
TA0CCTL1 = OUTMOD_7; // TACCR1 set/reset
TA0CCR1 = 10; // TACCR1 PWM Duty Cycle
TA0CTL = TASSEL__SMCLK | MC__UP | TACLR; // ACLK, up mode
}
void DMA_init(){
// Configure DMA channel 0
__data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &ADC12MEM0);
// Source block address
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
// Destination single address
DMA0SZ =256; // Block size
// DMA0CTL &= ~DMAIFG; //清楚中断标志,防止未发生中断前已置位
DMA0CTL = DMADT_4 | DMASRCINCR_0 | DMADSTINCR_3 | DMAIE; // Rpt, inc
DMACTL0|= DMA0TSEL_26; //DMA触发源ADCIFG
DMA0CTL|= DMAEN; // Enable DMA0
/*Configure DMA channel 1*/
__data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) &input);
DMA1SZ =256; // Block size
// DMA1CTL &= ~DMAIFG; //清楚中断标志,防止未发生中断前已置位
DMA1CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3 | DMAIE ; // Rpt, inc
}
void ADC12_init(){
ADC12CTL0 = ADC12SHT0_0 | ADC12ON; // Sampling time, S&H=4(4个采样保持AD时钟周期), ADC12 on开启AD
// Use TA0.1 to trigger, and repeated-single-channel 脉冲采样模式,触发源SAMPCON来自采样样本定时器,它的输入来自定时器TA0.1(数据手册) ,选择单通道重复转换模式,时钟源SMCLK
ADC12CTL1 = ADC12SHP | ADC12SHS_1 | ADC12CONSEQ_2 | ADC12SSEL_3;
// A1 ADC input select; Vref+ = AVCC 中断源选择,选择A1通道,序列未结束,参考电压默认没有设置
ADC12MCTL0 = ADC12INCH_3 | ADC12EOS;
ADC12CTL2 |= ADC12RES_2; //转换的位数12
// ADC12IER0 |= ADC12IE0; // Enable ADC interrupt 使能ADC12IFGO中断
ADC12IER2 |= ADC12TOVIE; //使能ADC转换时间溢出中断
ADC12IER2 |= ADC12OVIE; //使能MEM缓存存储器溢出中断位
ADC12CTL0 |= ADC12ENC ; // Start sampling/conversion 开启AD转换
__bis_SR_register(GIE); // Enter LPM0, enable interrupts
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
GPIO_INIT();
CLOCK_init();
TIMER_init();
DMA_init();
// __bis_SR_register(GIE); // 打开全局中断
/*
while(1){
P1OUT|= 0x01; // P1.0 = 1, LED on
DMA0CTL|= DMAREQ; // Trigger block transfer
}
*/
P1OUT |= BIT1; // P1.1 = 1
ADC12_init();
while(1){
if(DMA0flag==1){
switch(flag){
case 1:
DMA1CTL&= ~DMAEN;
__data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &buf[0]);
DMA1CTL|= DMAEN; // Enable DMA0
DMA1CTL|= DMAREQ; // 软件触发DMA1转移数据
DMA0flag=0;
break;
case 0:
DMA1CTL&= ~DMAEN;
__data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &buf[256]);
DMA1CTL|= DMAEN; // Enable DMA0
DMA1CTL|= DMAREQ; // 软件触发DMA1转移数据
DMA0flag=0;
break;
default :
break;
}
}
}
__no_operation();
return 0;
}
//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
if(flag==0){
DMA0CTL&= ~DMAEN;
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[256]);
DMA0CTL|= DMAEN; // Enable DMA0
DMA0flag=1;
flag=1;
}
else{
DMA0CTL&= ~DMAEN;
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
DMA0CTL|= DMAEN; // Enable DMA0
DMA0flag=1;
flag=0;
}
break;
case 4:
DMA1flag=1;
break; // DMA1IFG = DMA Channel 1
/*
case 6: break; // DMA2IFG = DMA Channel 2
case 8: break; // DMA3IFG = DMA Channel 3
case 10: break; // DMA4IFG = DMA Channel 4
case 12: break; // DMA5IFG = DMA Channel 5
case 14: break; // DMA6IFG = DMA Channel 6
case 16: break; // DMA7IFG = DMA Channel 7
default: break;*/
}
}
我把中断服务函数里面嵌套使用的switch改了,还是会进入空循环
#include "msp430.h" #include <stdint.h> int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT // Configure GPIO P1OUT = 0; P1DIR = BIT0; // For LED P4OUT = 0; P4DIR = BIT6; // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; // Configure DMA channel 0 __data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) 0x1C20); // Source block address __data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) 0x1C40); // Destination single address DMA0SZ = 16; // Block size DMA0CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3; // Rpt, inc DMA0CTL |= DMAEN | DMAIE; // Enable DMA0 __data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) 0x1C98); __data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) 0x1CB8); DMA1SZ = 16; // Block size DMA1CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3; // Rpt, inc DMA1CTL |= DMAEN | DMAIE; __bis_SR_register(GIE); while(1) { //P1OUT |= 0x01; // P1.0 = 1, LED on DMA0CTL |= DMAREQ; // Trigger block transfer DMA1CTL |= DMAREQ; //P1OUT &= ~0x01; // P1.0 = 0, LED off } } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=DMA_VECTOR __interrupt void DMA_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(DMAIV,16)) { case 0: break; case 2: // DMA0IFG = DMA Channel 0 P4OUT ^= BIT6; // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE break; case 4: // DMA1IFG = DMA Channel 1 P1OUT ^= BIT0; break; case 6: break; // DMA2IFG = DMA Channel 2 case 8: break; // DMA3IFG = DMA Channel 3 case 10: break; // DMA4IFG = DMA Channel 4 case 12: break; // DMA5IFG = DMA Channel 5 case 14: break; // DMA6IFG = DMA Channel 6 case 16: break; // DMA7IFG = DMA Channel 7 default: break; } }
我找到问题了,为了讲清楚问题,请先让我概述一下设计内容,系统时钟MCLK、SMCLK、ACLK,全设置为8MHz,定时器TB0和ADC12都使用没有任何分频处理的SMCLK时钟,TB0的CCR0设置为250,CCR1设置为10,这样可以产生周期32kHz的占空比4百分之的PWM信号,此信号作为ADC12的采样转换的触发信号,脉冲触发,DMA0通道设置ADC12的转换完成标志作为触发信号,这样ADC12每采样转换一次,DMA0就转移一次ADC12MEM0里面的数据。之前一直跳入系统自带的空循环是因为我设置了ADC12的溢出中断ADC12TOVIE和ADC12OVIE,产生了ADC12OVIE中断,因为没有设置这个中断服务函数,所以一直进入系统空函数,这就是之前的问题。
现在我有了一个新问题,为什么会产生这个ADC12OVIE中断?这个中断代表ADC12采样转换的数据存入ADC12MEM0寄存器,下一个转换数据存入之前,上一次的数据没有被读出,这里我不明白,TB031.25us产生一个上升沿脉冲,也就是ADC12也是这个时间间隔采样转换一次数据,DMA转移数据时间这么慢吗?不应该。我一步一步的调试,观察,第一种情况,把断电设置在DMA中断服务函数和ADC12中断服务函数那里,发现会一直产生ADC12OVIE中断,第二种情况,把断电设置在DMA0中断那里,切换地址都很正常,退出这个中断也正常,此时DMA0切换好了地址,按理说在往下步进,会重复被ADC12转换完成信号触发,可是还是和第一种情况一样,会进入ADC12OVIE中断,实在弄不懂是为什么
#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
volatile int buf[512];
volatile int result[256];
unsigned char bufflag=1;
unsigned char DMA0flag=1;
unsigned char DMA2flag=1;
void GPIO_INIT(){
/*Configure GPIOs to it's lowest power state*/
P1OUT = 0;
P1DIR = 0xFF;
P2OUT = 0;
P2DIR = 0xFF;
P3OUT = 0;
P3DIR = 0xFF;
P4OUT = 0;
P4DIR = 0xFF;
P5OUT = 0;
P5DIR = 0xFF;
P6OUT = 0;
P6DIR = 0xFF;
P7OUT = 0;
P7DIR = 0xFF;
P8OUT = 0;
P8DIR = 0xFF;
PJOUT = 0;
PJDIR = 0xFFFF;
P1SEL0 |= BIT3; // 配置1.3引脚为AD输入通道
P1SEL1 |= BIT3;
/* Output SMCLK,观察时钟源变化*/
P3DIR |= BIT4;
P3SEL1 |= BIT4;
P3SEL0 |= BIT4;
/*定时器TB0.1输出测试,不需要测试时请屏蔽*/
// P1SEL0 |= BIT4;
/* Disable the GPIO power-on default high-impedance mode to activate previously configured port settings*/
PM5CTL0 &= ~LOCKLPM5;
}
void CLOCK_init(){
/*Clock System Setup*/
CSCTL0_H = CSKEY_H; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
// Per Device Errata set divider to 4 before changing frequency to
// prevent out of spec operation from overshoot transient
CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata
CSCTL1 = DCOFSEL_6; // Set DCO to 8MHz
// Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
__delay_cycles(60);
CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers
CSCTL0_H = 0; // Lock CS Registers
}
void TIMER_init(){
/*使用定时器A1.1作为AD采样的触发信号,生成周期为32kHz,占空比为4%的PWM信号,该信号上升沿触发AD采样,配置如下*/
TB0CCR0 = 250; /* PWM 周期*/
TB0CCTL1 = OUTMOD_7; /* 定时器A的输出工作模式*/
TB0CCR1 = 10; /* PWM高电平占空比*/
TB0CTL = TASSEL__SMCLK | MC__UP | TACLR; /*定时器时钟源SMCLK,开启定时器*/
}
void ADC12_init(){
ADC12CTL0 = ADC12SHT0_0 | ADC12ON; // Sampling time, S&H=4(4个采样保持AD时钟周期), ADC12 on开启AD
// Use TB0.1 to trigger, and repeated-single-channel 脉冲采样模式,触发源SAMPCON来自采样样本定时器,它的输入来自定时器Tb0.1(数据手册) ,选择单通道重复转换模式,时钟源SMCLK
ADC12CTL1 = ADC12SHP | ADC12SHS_3 | ADC12CONSEQ_2 | ADC12SSEL_3;
// A1 ADC input select; Vref+ = AVCC 中断源选择,选择A3通道,序列未结束,参考电压默认没有设置
ADC12MCTL0 = ADC12INCH_3 | ADC12EOS;
ADC12CTL2 |= ADC12RES_2; //转换的位数12
// ADC12IER0 |= ADC12IE0; // Enable ADC interrupt 使能ADC12IFGO中断
ADC12IER2 |= ADC12TOVIE; //使能ADC转换时间溢出中断
ADC12IER2 |= ADC12OVIE; //使能MEM缓存存储器溢出中断位
ADC12CTL0 |= ADC12ENC ; // Start sampling/conversion 开启AD转换
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
GPIO_INIT();
CLOCK_init();
TIMER_init();
ADC12_init();
// Configure DMA channel 0
__data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &ADC12MEM0);
// Source block address
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
// Destination single address
DMA0SZ = 256; // Block size
DMACTL0 |= DMA0TSEL_26;
DMA0CTL = DMADT_4 | DMASRCINCR_3 | DMADSTINCR_3; // Rpt, inc
DMA0CTL |= DMAEN | DMAIE; // Enable DMA0
__data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &buf[0]);
__data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) &result);
DMA1SZ = 256; // Block size
DMA1CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3; // Rpt, inc
DMA1CTL |= DMAEN | DMAIE;
__bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_ISR will force exit
while(1)
{
if(DMA0flag==2){
DMA1CTL |= DMAREQ;
P1OUT |= 0x01; // P1.0 = 1, LED on
DMA0flag=1;
__no_operation();
}
}
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
DMA0CTL &= ~DMAEN;
if(bufflag==1){
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[256]);
DMA1CTL |= DMAEN | DMAIE;
}
else if(bufflag==2){
__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf[0]);
DMA1CTL |= DMAEN | DMAIE;
}
DMA0flag=2;
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break;
case 4: // DMA1IFG = DMA Channel 1
P1OUT ^= BIT0;
break;
case 6: break; // DMA2IFG = DMA Channel 2
case 8: break; // DMA3IFG = DMA Channel 3
case 10: break; // DMA4IFG = DMA Channel 4
case 12: break; // DMA5IFG = DMA Channel 5
case 14: break; // DMA6IFG = DMA Channel 6
case 16: break; // DMA7IFG = DMA Channel 7
default: break;
}
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_B_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_B_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(ADC12IV, ADC12IV__ADC12RDYIFG))
{
case ADC12IV__NONE: break; // Vector 0: No interrupt
case ADC12IV__ADC12OVIFG:
__no_operation();
break; // Vector 2: ADC12MEMx Overflow
case ADC12IV__ADC12TOVIFG:
__no_operation();
break; // Vector 4: Conversion time overflow
case ADC12IV__ADC12HIIFG: break; // Vector 6: ADC12BHI
case ADC12IV__ADC12LOIFG: break; // Vector 8: ADC12BLO
case ADC12IV__ADC12INIFG: break; // Vector 10: ADC12BIN
case ADC12IV__ADC12IFG0: // Vector 12: ADC12MEM0 Interrupt
break;
case ADC12IV__ADC12IFG1: break; // Vector 14: ADC12MEM1
case ADC12IV__ADC12IFG2: break; // Vector 16: ADC12MEM2
case ADC12IV__ADC12IFG3: break; // Vector 18: ADC12MEM3
case ADC12IV__ADC12IFG4: break; // Vector 20: ADC12MEM4
case ADC12IV__ADC12IFG5: break; // Vector 22: ADC12MEM5
case ADC12IV__ADC12IFG6: break; // Vector 24: ADC12MEM6
case ADC12IV__ADC12IFG7: break; // Vector 26: ADC12MEM7
case ADC12IV__ADC12IFG8: break; // Vector 28: ADC12MEM8
case ADC12IV__ADC12IFG9: break; // Vector 30: ADC12MEM9
case ADC12IV__ADC12IFG10: break; // Vector 32: ADC12MEM10
case ADC12IV__ADC12IFG11: break; // Vector 34: ADC12MEM11
case ADC12IV__ADC12IFG12: break; // Vector 36: ADC12MEM12
case ADC12IV__ADC12IFG13: break; // Vector 38: ADC12MEM13
case ADC12IV__ADC12IFG14: break; // Vector 40: ADC12MEM14
case ADC12IV__ADC12IFG15: break; // Vector 42: ADC12MEM15
case ADC12IV__ADC12IFG16: break; // Vector 44: ADC12MEM16
case ADC12IV__ADC12IFG17: break; // Vector 46: ADC12MEM17
case ADC12IV__ADC12IFG18: break; // Vector 48: ADC12MEM18
case ADC12IV__ADC12IFG19: break; // Vector 50: ADC12MEM19
case ADC12IV__ADC12IFG20: break; // Vector 52: ADC12MEM20
case ADC12IV__ADC12IFG21: break; // Vector 54: ADC12MEM21
case ADC12IV__ADC12IFG22: break; // Vector 56: ADC12MEM22
case ADC12IV__ADC12IFG23: break; // Vector 58: ADC12MEM23
case ADC12IV__ADC12IFG24: break; // Vector 60: ADC12MEM24
case ADC12IV__ADC12IFG25: break; // Vector 62: ADC12MEM25
case ADC12IV__ADC12IFG26: break; // Vector 64: ADC12MEM26
case ADC12IV__ADC12IFG27: break; // Vector 66: ADC12MEM27
case ADC12IV__ADC12IFG28: break; // Vector 68: ADC12MEM28
case ADC12IV__ADC12IFG29: break; // Vector 70: ADC12MEM29
case ADC12IV__ADC12IFG30: break; // Vector 72: ADC12MEM30
case ADC12IV__ADC12IFG31: break; // Vector 74: ADC12MEM31
case ADC12IV__ADC12RDYIFG: break; // Vector 76: ADC12RDY
default: break;
}
}