1.原理:

通过定时器每隔一段时间触发一次DAC转换,然后通过DMA发送正玄波码表值给DAC.

  • 当需要改变频率HZ时,只需要修改定时器频率即可(最高只能达到20KHz)
  • 当需要改变正玄波的正峰峰值/负峰峰值时,只需要修改正玄波码表即可

2.实现

代码如下所示(采用的是定时器2,DAC引脚是PA4)

#define HZ(x) (u16)(72000000/sizeof(Sine12bit)*2/x)     //计算Hz

#define DAC_DHR12R1 0x40007408 //外设DAC通道1的基地址

u16 Sine12bit[] = { //正弦波描点
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , }; /*************************************************************
Function : set_Sine12bit
Description : 设置正玄波码表
Input : MAX(正峰峰值) MIN(负峰峰值)
return : none
*************************************************************/
void Set_Sine12bit(float MAX,float MIN)
{
int i;
float jiaodu=; float MID=(MAX+MIN)/2.0; //中间峰值 if(MAX>3.3) MAX=3.3; else if(MAX<=MIN) MIN=;
for(i=;i<;i++)
{
jiaodu=i*0.0247369; //当i =127时,表示为180度,由于sin()是弧度制,所以需要转换
Sine12bit[i]= ((float)sin(jiaodu)*(MAX-MID)+MID)*1241.212; //1241.212是比例,等于4096/3.3
}
} /*************************************************************
Function : Set_Period
Description : 设置频率hz
Input : value(需要设置的频率hz值)
return : none
*************************************************************/
void Set_Period(u32 value)
{
TIM_ARRPreloadConfig(TIM2,DISABLE);
TIM2->ARR=HZ(value); //更新预装载值
TIM_ARRPreloadConfig(TIM2,ENABLE); } /*************************************************************
Function : TIM2_Int_Init
Description: 初始化定时器2
Input : Hz (需要初始化的频率hz值)
return : none
*************************************************************/
void TIM2_Int_Init(u32 Hz)
{ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//初始化定时器2与6的时钟 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = HZ(Hz); //正弦波频率设置
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //没有预分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时钟不分频 72M
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //增计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//更新TIM2输出触发
} /*************************************************************
Function : DAC_DMA_Config
Description: 初始化DAC和DMA
Input : none
return : none
*************************************************************/
void DAC_DMA_Config(void)
{
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//初始化DAC的时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//初始化DMA2的时钟 /*初始化GPIO*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;//DAC channel1和channel2对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); /*初始化DAC寄存器*/
DAC_StructInit(&DAC_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;//指定DAC1的触发定时器TIM2
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;//无波形产生
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //不是能DAC输出缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);//初始化DAC channel1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC channel1
DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DAC Channel1的DMA
/*初始化DMA寄存器*/
DMA_DeInit(DMA2_Channel3); //将DMA配置成默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1;//指定DMA2通道3的目标地址为DAC1_DHR12R1
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Sine12bit;//指定DMA的源地址为数组Sine12bit
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = sizeof(Sine12bit)/;//DMA缓冲区大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设机地址存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度为半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据宽度为半字
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//工作在循环缓存模式,数据传输数为0时,自动恢复配置初值
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//非常高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//通道未被设置成内存到内存模式,与循环模式相对
DMA_Init(DMA2_Channel3, &DMA_InitStructure);//初始化DMA
DMA_Cmd(DMA2_Channel3, ENABLE); //使能DMA的channel3 TIM_Cmd(TIM2, ENABLE); //最后开启TIM2转换
}

然后在main()函数里,调用USART_handler()

其中USART_handler()函数实现如下:

void USART_handler()
{
u8 len;
u32 hz; //获取HZ频率
float dac_max,dac_min; //获取DAC峰值 if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x2F;
USART_RX_BUF[len]=;
sscanf((char *)USART_RX_BUF,"%d,%f,%f",&hz,&dac_max,&dac_min);
printf("SET HZ = %d, MAX = %f,MIN = %f\r\n", hz,dac_max,dac_min); Set_Sine12bit(dac_max,dac_min); //更改峰值
Set_Period( hz); //更改频率 USART_RX_STA=;
}
}

3.进入串口试验

1)设置频率=50hz,正峰值=3.3V,负峰值=0V,串口则发送50,3.3,0.0,如下图所示:

示波器测量:

 

2)设置频率=100hz,正峰值=3V,负峰值=0V, 串口则发送100,3,0.0:

3)设置频率=100hz,正峰值=2V,负峰值=1V, 串口则发送100,2,1:

4)设置频率=1khz,正峰值=3.3V,负峰值=0V, 串口则发送1000,3.3,0: 

5)设置频率=20khz,正峰值=3.3V,负峰值=0V,串口则发送20000,3.3,0:   

 是不是很简单~

STM32-正弦波可调(50HZ~20KHZ可调、峰峰值0~3.3V可调)的更多相关文章

  1. Cloudera Hadoop 5& Hadoop高阶管理及调优课程(CDH5,Hadoop2.0,HA,安全,管理,调优)

    1.课程环境 本课程涉及的技术产品及相关版本: 技术 版本 Linux CentOS 6.5 Java 1.7 Hadoop2.0 2.6.0 Hadoop1.0 1.2.1 Zookeeper 3. ...

  2. [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析

    本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...

  3. spark 性能调优(一) 性能调优的本质、spark资源使用原理、调优要点分析

    转载:http://www.cnblogs.com/jcchoiling/p/6440709.html 一.大数据性能调优的本质 编程的时候发现一个惊人的规律,软件是不存在的!所有编程高手级别的人无论 ...

  4. elasticsearch5.3.0 bulk index 性能调优实践

    elasticsearch5.3.0 bulk index 性能调优实践 通俗易懂

  5. JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数

    jvm调优主要针对堆内存,堆内存分为:新生区.养老区和永久区 永久区存放的是系统jdk自身的interface和class的元数据,所以唯有新生区和养老区具有优化空间. 新生区:伊甸区和幸存者区.所有 ...

  6. Nginx-PHP优化设置 + lnmp调优的关键影响因素 + php-fpm + nginx返回码 + tcp调优 + 最大文件描述符

    https://www.cnblogs.com/zengkefu/p/5602473.html最大文件描述符 https://blog.csdn.net/fanren224/article/detai ...

  7. 性能调优的本质、Spark资源使用原理和调优要点分析

    本课主题 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...

  8. JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)

    性能分析工具jstatjmapjhatjstack 前提概要:         JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jsta ...

  9. JVM性能调优(3) —— 内存分配和垃圾回收调优

    前序文章: JVM性能调优(1) -- JVM内存模型和类加载运行机制 JVM性能调优(2) -- 垃圾回收器和回收策略 一.内存调优的目标 新生代的垃圾回收是比较简单的,Eden区满了无法分配新对象 ...

随机推荐

  1. 详解小白利用eclipse+CDT+MinGW搭建C++开发环境

    安装JDK.安装Eclipse     2.打开Eclipse 找到“help”下的“Eclipse marketplace” 如图:    3.选择相应的C插件: 因为安装过所以显示installe ...

  2. memcache 总结笔记

    (一):基础概念 memcache是什么? Memcache 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态 ...

  3. js实现单双行文本溢出添加省略号

    # 单双行文本溢出省略 ``` // 2. 当内容过多的时候,单行省略号: overflow: hidden; text-overflow:ellipsis; white-space: nowrap; ...

  4. Tram

    Tram 题目大意:给你一个图,这个图上有n点和边.点上有开关,开关开始指向一条道路,拨动开关可以使开关指向由开关出发的任意一条路径,读入,a,b,求,至少要拨动几次才能从a点走到b点. 注释:n&l ...

  5. python实现的txt目录树

    首先,我先表述一下我的需求: 我记笔记比较乱,但我比较容易"半途而废".文件夹很多,但大都只有一两个文件.... 所以我需要一种方式,能在不逐个打开文件夹的前提下,"看到 ...

  6. shell之九九乘法表

    echo -n 不换行输出   $echo -n "123" $echo "456"   最终输出  123456   而不是 123 456   echo - ...

  7. webpack----webpack4尝鲜

    安装v4.0.0-beta.0 yarn add webpack@next webpack-cli --dev 或者 npm install webpack@next webpack-cli --sa ...

  8. 记录python接口自动化测试--利用unittest生成测试报告(第四目)

    前面介绍了是用unittest管理测试用例,这次看看如何生成html格式的测试报告 生成html格式的测试报告需要用到 HTMLTestRunner,在网上下载了一个HTMLTestRunner.py ...

  9. 2017-2018-1 1623 bug终结者 冲刺003

    bug终结者 冲刺003 by 王旌含 今日任务:优化界面布局,提供图片素材 需求 app图标.主界面图.主界面中按钮图:选择关卡图.关卡按键图:游戏中的小人.箱子.地板.墙.目的地:方向按钮:重置按 ...

  10. 2017 清北济南考前刷题Day 3 morning

    实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstd ...