提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
这个程序非常简单,说白了就是每隔一段时间改变引脚输出的电压,就能得到一个正弦波。
主要是为了方便大家调试FFT,有一个输入大于0小于3.3V取样信号,方便大家学习。
一、如何产生正弦波?
本文采用查表法的方式生成一个数值范围为[0,4096]的正弦波数组,通过定时器更新中断不断以DAC进行输出,从而产生一个正弦波,并且通过改变定时器的预装载值(ARR)或者预分频系数(psc),改变进入中断的时间进而改变正弦波频率。
二、生成采样数值函数
代码如下:
void out_sine(void)
{
double index = 250;//250个数据
float pi = 3.141592;
int fori = 0;
float outv = 0;
for(;fori <index;fori++)
{
outv = 0.5*(sin((2*pi)/index*fori)+1)*4095;
printf("%.0f,\t",outv);
if(!((fori+1)%8))
printf("\r\n");//将数据打印出来
}
}
下表是通过串口软件打印出来的数据,有了这个一维数组我们只需要将数组里的值依次赋给DAC就能得到正弦波啦。
const u16 Sine12bit_250[250] = {
2048, 2099, 2150, 2202, 2253, 2304, 2355, 2406,
2456, 2507, 2557, 2606, 2656, 2705, 2753, 2801,
2849, 2896, 2942, 2988, 3034, 3079, 3123, 3166,
3209, 3251, 3292, 3333, 3372, 3411, 3449, 3486,
3522, 3558, 3592, 3625, 3657, 3689, 3719, 3748,
3776, 3803, 3829, 3854, 3878, 3900, 3921, 3942,
3961, 3978, 3995, 4010, 4024, 4037, 4048, 4059,
4068, 4075, 4082, 4087, 4091, 4094, 4095, 4095,
4094, 4091, 4087, 4082, 4075, 4068, 4059, 4048,
4037, 4024, 4010, 3995, 3978, 3961, 3942, 3921,
3900, 3878, 3854, 3829, 3803, 3776, 3748, 3719,
3689, 3657, 3625, 3592, 3558, 3522, 3486, 3449,
3411, 3372, 3333, 3292, 3251, 3209, 3166, 3123,
3079, 3034, 2988, 2942, 2896, 2849, 2801, 2753,
2705, 2656, 2606, 2557, 2507, 2456, 2406, 2355,
2304, 2253, 2202, 2150, 2099, 2048, 1996, 1945,
1893, 1842, 1791, 1740, 1689, 1639, 1588, 1538,
1489, 1439, 1390, 1342, 1294, 1246, 1199, 1153,
1107, 1061, 1016, 972, 929, 886, 844, 803,
762, 723, 684, 646, 609, 573, 537, 503,
470, 438, 406, 376, 347, 319, 292, 266,
241, 217, 195, 174, 153, 134, 117, 100,
85, 71, 58, 47, 36, 27, 20, 13,
8, 4, 1, 0, 0, 1, 4, 8,
13, 20, 27, 36, 47, 58, 71, 85,
100, 117, 134, 153, 174, 195, 217, 241,
266, 292, 319, 347, 376, 406, 438, 470,
503, 537, 573, 609, 646, 684, 723, 762,
803, 844, 886, 929, 972, 1016, 1061, 1107,
1153, 1199, 1246, 1294, 1342, 1390, 1439, 1489,
1538, 1588, 1639, 1689, 1740, 1791, 1842, 1893,
1945, 1996,
};
2.通过高级定时器TIM1更新中断控制DAC输出
代码如下:
#define CLIP_ROT(V,MIN,MAX) ( ( V>MAX?MIN:(V<MIN?MAX:V) ) )
void AdcPushData()
{
static int DAC_index_1 = 0;
DAC_SetChannel1Data(DAC_Align_12b_R,(Sine12bit_250[DAC_index_1])*DacAmp/10);//250个点
4Khz(0.4ms)
DAC_index_1++;
DAC_index_1 = CLIP_ROT(DAC_index_1,0,250);
}
void Timer1_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrecture;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);/*使能定时器1的时钟*/
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;/*定时器1的中断通道使能*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/*定时器1的中断通道使能*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;/*抢占优先级*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;/*响应优先级*/
NVIC_Init(&NVIC_InitStructure);/*配置中断分组,并使能中断*/
TIM_TimeBaseInitStrecture.TIM_Period = arr;/*重装载寄存器*/
TIM_TimeBaseInitStrecture.TIM_Prescaler = psc;/*预分配*/
TIM_TimeBaseInitStrecture.TIM_ClockDivision = TIM_CKD_DIV1;/*时钟分频*/
TIM_TimeBaseInitStrecture.TIM_CounterMode = TIM_CounterMode_Up;/*向上计数*/
TIM_TimeBaseInitStrecture.TIM_RepetitionCounter = 0;/*重复计数寄存器*/
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrecture);/*初始化*/
TIM_ClearFlag(TIM1,TIM_FLAG_Update);/*清更新标志位*/
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);/*使能中断*/
TIM_Cmd(TIM1,ENABLE);/*使能计数*/
}
void TIM1_UP_TIM10_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET){//判断TIM中断发生与否:TIM 中断源
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除中断标志位,否则卡死在中断里
/***************在此处添加中断执行内容******************/
AdcPushData();
LED1 = ~LED1;
}
}
中断配置好了就可以输出一个好看的正弦波了,那怎么调频和调幅呢?
二、通过四个按钮控制输出的频率和幅度
代码如下:
static int DacAmp = 0.0;
void Sine()
{
u16 key=KEY_Scan(0);
static u16 F = 128 - 1 ;//默认50HZ
switch(key)
{
case WKUP_PRES:DacAmp +=1;break;//
case KEY1_PRES:DacAmp -=1;break;
case KEY2_PRES:F += 10;break;//改变TIM1的预装载值,从而改变频率
case KEY0_PRES:F -= 10;break;
default:break;
}
DacAmp = CLIP_ROT(DacAmp,0,10);
TIM1->ARR = F;// 改变预分配系数也是可行的,(PSC)TIM1->PSC =F;
}
按下WKUP_PRES和KEY1_PRES,正弦波幅值变化,KEY2_PRES和KEY0_PRES控制频率变化。
三、下面是我的实测波形
附上代码:链接:https://pan.baidu.com/s/1aXAH2Qu5vF8uVKZdXpQx0g?pwd=1234
提取码:1234
需要的自取哈,代码写的不好,就当交流学习。
总结
额,不知道写啥,有问题请留言,如果觉得有用的话,请点个赞,不胜感激。