CH32V307 DAC输出正弦波
本文介绍使用CH32V307的DAC功能,从输出管脚输出正弦波。
使用到的硬件
CH32V307芯片模块包含2个可配置8/12位数模转换器,其引脚分别位PA4和PA5,作为DAC功能时,分别对应DAC_Channel1和DAC_Channel2两个通道。数据手册中信息如下。
输出程序编写
DDS是控制MCU输出任意波形的常见技术,其实现方法是通过使用查表得方式确定某个时间点DAC的输出电平,设定一个时间间隔,每隔固定时间查询一次表,确定当前输出的DAC的值。具体实现方法是设定一个正弦波DAC数组,开启DMA功能,将数组中的值传递到DAC的输出寄存器中,DMA使用定时器触发从而实现对周期的控制。具体的代码如下:
#include "debug.h"
#define Num 64
uint32_t DAC_Value[Num]={2048,2248,2447,2642,2831,3013,3185,3347,3496,3631,3750,3854,3940,4007,4056,4086,
4095,4086,4056,4007,3940,3854,3750,3631,3496,3347,3185,3013,2831,2642,2447,2248,
2048,1847,1648,1453,1264,1082,910 ,748 ,599 ,464 ,345 ,241 ,155 ,88 ,39 ,9 ,
0 ,9 ,39 ,88 ,155 ,241 ,345 ,464 ,599 ,748 ,910 ,1082,1264,1453,1648,1847};
uint32_t Dual_DAC_Value[Num];
void Dual_Dac_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
DAC_InitTypeDef DAC_InitType={0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
DAC_InitType.DAC_Trigger=DAC_Trigger_T4_TRGO;
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;
DAC_Init(DAC_Channel_1,&DAC_InitType);
DAC_Init(DAC_Channel_2,&DAC_InitType);
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
DAC_DMACmd(DAC_Channel_1,ENABLE);
DAC_DMACmd(DAC_Channel_2,ENABLE);
DAC_SetDualChannelData(DAC_Align_12b_R, 0x123,0x321);
}
void Dac_Dma_Init(void)
{
DMA_InitTypeDef DMA_InitStructure={0};
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
DMA_StructInit( &DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->RD12BDHR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Dual_DAC_Value[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = Num;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel3, &DMA_InitStructure);
DMA_Cmd(DMA2_Channel3, ENABLE);
}
void Timer4_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 3600-1;
TIM_TimeBaseStructure.TIM_Prescaler =0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);
TIM_Cmd(TIM4, ENABLE);
}
int main(void)
{
uint8_t i=0;
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\\\\r\\\\n",SystemCoreClock);
printf( "ChipID:%08x\\\\r\\\\n", DBGMCU_GetCHIPID() );
printf("Dual DAC Generation Test\\\\r\\\\n");
for(i=0;i<Num;i++)
{
Dual_DAC_Value[i]=(DAC_Value[i]<<16) + DAC_Value[i];
printf("0x%08x\\\\r\\\\n",Dual_DAC_Value[i]);
}
Dual_Dac_Init();
Dac_Dma_Init();
Timer4_Init();
while(1)
{
printf("CNT=%d\\\\r\\\\n",TIM4->CNT);
printf("RD12BDHR=0x%04x\\\\r\\\\n",DAC->RD12BDHR);
printf("DOR1=0x%04x\\\\r\\\\n",DAC->DOR1);
printf("DOR2=0x%04x\\\\r\\\\n",DAC->DOR2);
Delay_Ms(500);
}
}
将开发板的输出引脚接到示波器上,可以看到输出的波形