CH559L单片机DMA方式在手工选择通道模式下AD采样数据串口输出

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH559L单片机DMA方式在手工选择通道模式下AD采样数据串口输出相关的知识,希望对你有一定的参考价值。

【CH559L单片机】DMA方式在手工选择通道模式下AD采样数据串口输出


✨本篇属于上一篇背景下的细分篇。

  • ADC数据串口打印:

👉通过一个10K可调定位器,连接到P11端口,一端接3.3V一端接GND.

🧾有人会有疑惑,前面都实现了USB CDC虚拟串口信息输出,为什么还要占用一个串口来作为调试数据信息的输出,这不仅浪费了硬件资源,也将调试配置增添了成本。其实尝试了将其整合到一块,调试时,发现在通过DMA方式ADC采用时打印不出数据。时有时无,整得令人无语,后面看了一下USB CDC相关的驱动代码好像也用到了DMA资源,可能是这个方面的原因导致在使用USB CDC虚拟串口输出 ADC数据时有时无的情况。

🌿DMA ADC采样方式:手工选择通道模式自动交替通道模式

在官方给出的参考案例当中,已经给出了 自动交替通道模式下的使用案例,这里就不在表述了,注意在使用官方案例的时,在串口打印的数据问题,这里也不在表述了,具体细节问题请看前面那篇文章。

🍃手工选择通道模式代码

  • 📌案例来源WCH官网地址:https://www.wch.cn/products/CH559.html
  • ADCAutoDMA.C修改而来。
  • 手工选择通道,配置方法如下:

ADC_CTRL &= ~bADC_CHANN_MOD0; //	手工选择通道
//ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推	
ADC_CHANN =0x01 << 1;//手工指定通道1
//ADC_CHANN = 0x02;	//同上
  • 📢采用数据说明:

📗每次采样6次,抛弃第一次和最后一次采样的数据,将第2次到第5次的数据求和,再取平均值。数据没有像官方案例那样存进Xdata区。

  • 🎈ADC采样引脚P11

/********************************** (C) COPYRIGHT *******************************
* File Name          : ADCAutoDMA.C
* Author             : WCH
* Version            : V1.3
* Date               : 2016/6/24
* Description        : CH559的ADC自动DMA方式采样操作,手工选择通道模式,采样位数设置为11位 ,采样引脚P11             				   
*******************************************************************************/
#include "..\\DEBUG.C"                                                          //调试信息打印
#include "..\\DEBUG.H"
#include <string.h>
#define ADCCount 6
UINT16X	ADCbuf[ ADCCount ];// _at_ 0x0040 ; //存储ADC采样数据
UINT8 Flag;

#pragma  NOAREGS

/*******************************************************************************
* Function Name  : InitADCInterrupt()
* Description    : ADC中断初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void InitADCInterrupt()

//  ADC_SETUP |= bADC_IE_FIFO_OV;                                             //使能FIFO溢出中断
//  ADC_SETUP |= bADC_IE_AIN7_LOW;                                            //使能AIN7低电平中断
//  ADC_SETUP |= bADC_IE_ACT;                                                 //ADC完成中断
    IE_ADC = 1;                                                               //使能ADC中断


/*******************************************************************************
* Function Name  : InitADCAuto()
* Description    : ADC自动采样初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void InitADCAuto()

    P1_IE = 0x00;  //关闭P1口其他数据功能,如果只用部分通道,可根据需要设定,否则影响IO正常使用
    ADC_SETUP |= bADC_POWER_EN;    //ADC电源使能
	
    ADC_CK_SE |= (MASK_ADC_CK_SE & 0x0C);  //设置12分频
    ADC_CTRL &= ~MASK_ADC_CYCLE;
    ADC_CTRL |= 0x0C;//设置ADC自动采样周期
	
    ADC_CTRL &= ~bADC_CHANN_MOD1;   //1101 1111                                    
//    ADC_CTRL |= bADC_CHANN_MOD0; //0001 0000自动通道选择通道0和通道1

	ADC_CTRL &= ~bADC_CHANN_MOD0; //	手工选择通道
	//ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推
	ADC_CHANN =0x01 << 1;//手工指定通道1
//	ADC_CHANN = 0x02;//手工指定通道1
	
	ADC_EX_SW |= bADC_RESOLUTION;//采样位数11bit:2048
	//	ADC_EX_SW &= ~bADC_RESOLUTION; //采样位数10bit:1024
    mDelayuS(100);  //确保ADC正常启动	


/*******************************************************************************
* Function Name  : InitADCDMA(UINT16 addr,UINT8 num)
* Description    : ADC的DMA初始化
* Input          : UINT16 addr,DMA起始地址
                   UINT8 num,DMA剩余计数
* Output         : None
* Return         : None
*******************************************************************************/
void InitADCDMA( )

    ADC_DMA = ADCbuf; //设置DMA起始地址
    ADC_DMA_CN = ADCCount; //设置DMA剩余计数
    ADC_SETUP |= bADC_DMA_EN;//使能DMA和中断


/*******************************************************************************
* Function Name  : ADCInterrupt(void)
* Description    : ADC 中断服务程序
*******************************************************************************/
void ADCInterrupt( void ) interrupt INT_NO_ADC using 1   //ADC中断服务程序,使用寄存器组1

  	printf("%02X  ",(UINT16)ADC_STAT);  //DC 11011100  f8 11111000
    if(ADC_STAT & bADC_IF_DMA_END)  //DMA完成中断
    
    	Flag = 1;
    	ADC_STAT |= bADC_IF_DMA_END; //清中断
			printf("DMA完成中断 \\n");  
    
    if(ADC_STAT & bADC_IF_FIFO_OV)  //ADC的FIFO溢出中断
    
    	ADC_STAT |= bADC_IF_FIFO_OV; //清中断
    
    if(ADC_STAT & bADC_IF_AIN7_LOW) //AIN7低电平中断
    
    	ADC_STAT |= bADC_IF_AIN7_LOW;//清中断
    
    if(ADC_STAT & bADC_IF_ACT) //ADC完成中断
    
    	ADC_STAT |= bADC_IF_ACT; //清中断
			printf("ADC完成中断 \\n");  
    


void main( ) 

    UINT8 i;
	UINT32X total=0;
    mDelaymS(30);//上电延时,等待内部晶振稳定,必加 
  CfgFsys( );//CH559时钟选择配置
    mInitSTDIO( );//串口0,可以用于调试
    printf("start ...\\n"); 
    Flag = 0;
//ADC采样有8个通道,在P1口,通道n 分别ADC_CHANN对应 (0x01 << n) ,如通道0是0x01,通道1是0x02依次类推	
    InitADCInterrupt(); //ADC自动采样初始化
    InitADCAuto();//ADC中断初始化
    InitADCDMA();

    EA = 1;//开启全局中断
    while(1)
     
      if(Flag)
	    
				ADC_SETUP &= ~bADC_DMA_EN;//关闭DMA和中断
	    	for( i=1;i<5;i++)
	    	

	    	    printf("%hu  ",ADCbuf[i]);//初次和最后一次采样值建议丢弃	
					total +=ADCbuf[i];					
	    	
				total =total/4;
				printf("ADC_value=:%lu  \\n",total);//初次和最后一次采样值建议丢弃				
//				memset(ADCbuf, 0, sizeof(ADCbuf));//清空数组
				total=0;
	    	Flag = 0;
				ADC_DMA = ADCbuf; //设置DMA起始地址
				ADC_DMA_CN=ADCCount;
				ADC_SETUP |= bADC_DMA_EN;//使能DMA和中断

//				InitADCDMA( );
	    
			 mDelaymS(1000);
			
    

时钟配置函数: CfgFsys( );//CH559时钟选择配置

我这里采用的是外部时钟源,根据自己的开发板自行选择。这里的代码是在官方的代码基础上调整过的。

/*******************************************************************************
* Function Name  : CfgFsys( )
* Description    : CH559时钟选择和配置函数,默认使用内部晶振12MHz,如果定义了FREQ_SYS可以
                   根据PLL_CFG和CLOCK_CFG配置得到,公式如下:
                   Fsys = (Fosc * ( PLL_CFG & MASK_PLL_MULT ))/(CLOCK_CFG & MASK_SYS_CK_DIV);
                   具体时钟需要自己配置
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
void	CfgFsys( )  

#if OSC_EN_XT
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;                                                 
	CLOCK_CFG |= bOSC_EN_XT;                                                   //使能外部晶振
    mDelaymS(10);
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;   
	CLOCK_CFG &= ~bOSC_EN_INT;
	SAFE_MOD = 0x00; 

#else
	SAFE_MOD = 0x55;                                                           //开启安全模式
  SAFE_MOD = 0xAA;                                                 
 	CLOCK_CFG &= ~MASK_SYS_CK_DIV;
//  CLOCK_CFG |= 6;                                                            //配置系统时钟48MHz
//  CLOCK_CFG |= 8;                                                            //配置系统时钟36MHz
//  CLOCK_CFG |= 10;                                                           //配置系统时钟28.8MHz
  CLOCK_CFG |= 12;                                                           //配置系统时钟24MHz
//  CLOCK_CFG |= 16;                                                           //配置系统时钟18MHz  
/*56MHz
// 	CLOCK_CFG &= ~MASK_SYS_CK_DIV;
//  CLOCK_CFG |= 6;                                                            //配置系统时钟56MHz    
    PLL_CFG = 0xFC;
*/	
    SAFE_MOD = 0xFF;                                                           //关闭安全模式  
//  如果修改主频,要同时修改FREQ_SYS,否则会造成延时函数不准
#endif 


以上是关于CH559L单片机DMA方式在手工选择通道模式下AD采样数据串口输出的主要内容,如果未能解决你的问题,请参考以下文章

CH559L单片机ADC介绍以及ADC采样案例

CH559L单片机定时器0-自动重装载模式下控制led闪烁

CH559l单片机入门篇通过串口打印内部ID信息

CH559L单片机CDC虚拟串口下数据环路测试案例

CH559L单片机PWM功能和示例介绍

CH559L单片机PWM功能和示例介绍