ADC_DMA程序调试中卡了很久的一个小问题,解决了!
这几天,在学习ADC_DMA程序,参考“STC32G-DEMO-CODE-V9.6-20240418”实验程序中“60-DMA-ADC采样数据自动存储”文件加中“16路ADC转换使用DMA-串口2返回结果”工程文件进行程序改写。
原来的程序对16路进行DMA自动扫描,然后在串口2输出结果,每个通道采集4次,调试能正常执行。
然后把串口2改成串口1输出,调试正常。在原程序中把16路,改成任意几路,调试正常。
接着我从头自己仿照写程序,16路扫描功能一样,调试正常。接着当我修改转换通道数量时,发生了问题,转换完成,没有打印输出。我自己写的源程序如下:
- #include "STC32G12K128.h"
- #include "intrins.h"
- #include "stdio.h"
-
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
-
- #define MAIN_Fosc 24000000L //定义主时钟
-
- #define ADC_CH 4 /* 1~16, ADC转换通道数, 需同步修改 DMA_ADC_CHSW 转换通道 */
- #define ADC_DATA 4 /* 6~n, 每个通道ADC转换数据总数, 2*转换次数+4, 需同步修改 DMA_ADC_CFG2 转换次数 */
- /**************定义引脚*****************/
-
- /**************全局变量*****************/
- bit DmaFlag;
- u8 xdata DmaBuffer[ADC_CH][ADC_DATA*2+4];
-
- /**************函数声明*****************/
- void GPIO_init(); //GPIO口初始化
- void delay_ms(u8 ms);
- void Uart1_Init(); //115200bps@24.000MHz
- void ADC_init(); // ADC初始化
- void DMA_Config(void); //DMA初始化
-
- /******************** 主函数 **************************/
- void main(void)
- {
- u8 i,n;
-
- //初始化
- WTST = 0; //设置程序指令延时参数
- EAXFR = 1; //扩展寄存器(XFR)访问使能
- CKCON = 0; //提高访问XRAM速度
-
- GPIO_init();//GPIO口初始化
- ADC_init(); // ADC初始化
-
- Uart1_Init(); //115200bps@24.000MHz
- DMA_Config();
- EA = 1; //允许总中断
- printf("STC32G系列ADC DMA测试程序!\r\n");
-
- DmaFlag=0;
- while(1)
- {
- delay_ms(200);
- if(DmaFlag)
- {
- printf("ADC DMA完成!\r\n");
- DmaFlag = 0;
- for(i=0; i<ADC_CH; i++) //3个通道
- {
- for(n=0; n<(ADC_DATA*2+4); n++)
- {
- printf("0x%02x ",DmaBuffer[i][n]);
- }
- printf("\r\n");
- }
- printf("\r\n");
-
- DMA_ADC_CR = 0xc0; //bit7 1:Enable ADC_DMA, bit6 1:Start ADC_DMA
- }
- }
- }
- /******************** 子函数 **************************/
- void GPIO_init()//GPIO口初始化
- {
- P0M1 = 0x7f; P0M0 = 0x00; //设置要做ADC的IO做高阻输入
- P1M1 = 0xfb; P1M0 = 0x00; //设置要做ADC的IO做高阻输入
- P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
- P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
- P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
- P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
- P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
- P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
- }
- void delay_ms(u8 ms)
- {
- u16 i;
- do
- {
- i = MAIN_Fosc / 6000;
- while(--i);
- }while(--ms);
- }
- void Uart1_Init(void) //115200bps@24.000MHz
- {
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x01; //串口1选择定时器2为波特率发生器
- AUXR |= 0x04; //定时器时钟1T模式
- T2L = 0xCC; //设置定时初始值
- T2H = 0xFF; //设置定时初始值
- AUXR |= 0x10; //定时器2开始计时
- TI=1; //使用“printf()函数”,TI初始化一定要置1
- }
-
- void ADC_init() // ADC初始化
- {
- ADCCFG = 0x2f; //设置 ADC 时钟为系统时钟/2/16,数据结果右对齐 ADC_RES 低四位+ ADC_RESL 8位
- ADCTIM = 0x3f; //设置 ADC 内部时序,ADC采样时间建议设最大值
- ADC_CONTR = 0x80; //使能 ADC 模块,需等待1ms后稳定
- }
- /******************** DMA初始化 **************************/
- void DMA_Config(void)
- {
- DMA_ADC_STA = 0x00; //中断标志位复位
- DMA_ADC_CFG = 0x80; //开启ADC_DMA中断,中断优先级最低,数据总线访问优先级最低
-
- DMA_ADC_RXAH = (u8)((u16)DmaBuffer >> 8); //ADC转换数据存储地址
- DMA_ADC_RXAL = (u8)((u16)DmaBuffer);
-
- DMA_ADC_CFG2 = 0x09; //每个通道ADC转换次数:4
- DMA_ADC_CHSW0 = 0x0d; //ADC通道使能寄存器 ADC3-P1.3,ADC0-P1.0
- DMA_ADC_CHSW1 = 0x80; //ADC15-内部测试电压1.19V
-
- DMA_ADC_CR = 0xc0; //bit7 1:Enable ADC_DMA, bit6 1:Start ADC_DMA
- }
-
- void ADC_DMA_Interrupt(void) interrupt 13
- {
- if (DMA_ADC_STA & 0x01) //发送完成
- {
- DMA_ADC_STA =0; //复位中断标志位
- DmaFlag = 1; //完成标志位置1
- }
- }
复制代码
这段代码怎么都无法打印输出结果。
但是只要把转换通道改成16路通道,就可以正常打印输出。修改的地方如下,用多行注释标注的地方:
- /******************** DMA初始化 **************************/
- void DMA_Config(void)
- {
- DMA_ADC_STA = 0x00; //中断标志位复位
- DMA_ADC_CFG = 0x80; //开启ADC_DMA中断,中断优先级最低,数据总线访问优先级最低
-
- DMA_ADC_RXAH = (u8)((u16)DmaBuffer >> 8); //ADC转换数据存储地址
- DMA_ADC_RXAL = (u8)((u16)DmaBuffer);
-
- DMA_ADC_CFG2 = 0x09; //每个通道ADC转换次数:4
- /*********************************************************************/
- DMA_ADC_CHSW0 = 0xff; //ADC通道使能寄存器 ADC3-P1.3,ADC0-P1.0
- DMA_ADC_CHSW1 = 0xff; //ADC15-内部测试电压1.19V</font>
- /*********************************************************************/
- DMA_ADC_CR = 0xc0; //bit7 1:Enable ADC_DMA, bit6 1:Start ADC_DMA
- }
复制代码
这个问题,我查了很久,最终和源程序一条一条对比尝试,终于找到问题。下面时找到DEBUG后,修改后的程序,就在主程序中删掉了一条指令就正常了,转换几路通道都可以。
- #include "STC32G12K128.h"
- #include "intrins.h"
- #include "stdio.h"
-
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
-
- #define MAIN_Fosc 24000000L //定义主时钟
-
- #define ADC_CH 4 /* 1~16, ADC转换通道数, 需同步修改 DMA_ADC_CHSW 转换通道 */
- #define ADC_DATA 4 /* 6~n, 每个通道ADC转换数据总数, 2*转换次数+4, 需同步修改 DMA_ADC_CFG2 转换次数 */
- /**************定义引脚*****************/
-
- /**************全局变量*****************/
- bit DmaFlag;
- u8 xdata DmaBuffer[ADC_CH][ADC_DATA*2+4];
-
- /**************函数声明*****************/
- void GPIO_init(); //GPIO口初始化
- void delay_ms(u8 ms);
- void Uart1_Init(); //115200bps@24.000MHz
- void ADC_init(); // ADC初始化
- void DMA_Config(void); //DMA初始化
-
-
-
- /******************** 主函数 **************************/
- void main(void)
- {
- u8 i,n;
-
- //初始化
- WTST = 0; //设置程序指令延时参数
- EAXFR = 1; //扩展寄存器(XFR)访问使能
- CKCON = 0; //提高访问XRAM速度
-
- GPIO_init();//GPIO口初始化
- ADC_init(); // ADC初始化
-
- Uart1_Init(); //115200bps@24.000MHz
- DMA_Config();
- EA = 1; //允许总中断
- printf("STC32G系列ADC DMA测试程序!\r\n");
-
- while(1)
- {
- delay_ms(200);
- if(DmaFlag)
- {
- printf("ADC DMA完成!\r\n");
- DmaFlag = 0;
- for(i=0; i<ADC_CH; i++) //3个通道
- {
- for(n=0; n<(ADC_DATA*2+4); n++) //
- {
- printf("0x%02x ",DmaBuffer[i][n]);
- }
- printf("\r\n");
- }
- printf("\r\n");
-
- DMA_ADC_CR = 0xc0; //bit7 1:Enable ADC_DMA, bit6 1:Start ADC_DMA
- }
- }
- }
- /******************** 子函数 **************************/
- void GPIO_init()//GPIO口初始化
- {
- P0M1 = 0x7f; P0M0 = 0x00; //设置要做ADC的IO做高阻输入
- P1M1 = 0xfb; P1M0 = 0x00; //设置要做ADC的IO做高阻输入
- P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
- P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
- P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
- P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
- P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
- P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
- }
- void delay_ms(u8 ms)
- {
- u16 i;
- do
- {
- i = MAIN_Fosc / 6000;
- while(--i);
- }while(--ms);
- }
- void Uart1_Init(void) //115200bps@24.000MHz
- {
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x01; //串口1选择定时器2为波特率发生器
- AUXR |= 0x04; //定时器时钟1T模式
- T2L = 0xCC; //设置定时初始值
- T2H = 0xFF; //设置定时初始值
- AUXR |= 0x10; //定时器2开始计时
- TI=1; //使用“printf()函数”,TI初始化一定要置1
- }
-
- void ADC_init() // ADC初始化
- {
- ADCCFG = 0x2f; //设置 ADC 时钟为系统时钟/2/16,数据结果右对齐 ADC_RES 低四位+ ADC_RESL 8位
- ADCTIM = 0x3f; //设置 ADC 内部时序,ADC采样时间建议设最大值
- ADC_CONTR = 0x80; //使能 ADC 模块,需等待1ms后稳定
- }
- /******************** DMA初始化 **************************/
- void DMA_Config(void)
- {
- DMA_ADC_STA = 0x00; //中断标志位复位
- DMA_ADC_CFG = 0x80; //开启ADC_DMA中断,中断优先级最低,数据总线访问优先级最低
-
- DMA_ADC_RXAH = (u8)((u16)DmaBuffer >> 8); //ADC转换数据存储地址
- DMA_ADC_RXAL = (u8)((u16)DmaBuffer);
-
- DMA_ADC_CFG2 = 0x09; //每个通道ADC转换次数:4
- DMA_ADC_CHSW0 = 0x0d; //ADC通道使能寄存器 ADC3-P1.3,ADC0-P1.0
- DMA_ADC_CHSW1 = 0x80; //ADC15-内部测试电压1.19V
-
- DMA_ADC_CR = 0xc0; //bit7 1:Enable ADC_DMA, bit6 1:Start ADC_DMA
- }
-
- void ADC_DMA_Interrupt(void) interrupt 13
- {
- if (DMA_ADC_STA & 0x01) //发送完成
- {
- DMA_ADC_STA =0; //复位中断标志位
- DmaFlag = 1; //完成标志位置1
- }
-
- }
复制代码
|