STM32-正弦波可调(50HZ~20KHZ可调、峰峰值0~3.3V可调)
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可调)的更多相关文章
- 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. ...
- [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析
本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- spark 性能调优(一) 性能调优的本质、spark资源使用原理、调优要点分析
转载:http://www.cnblogs.com/jcchoiling/p/6440709.html 一.大数据性能调优的本质 编程的时候发现一个惊人的规律,软件是不存在的!所有编程高手级别的人无论 ...
- elasticsearch5.3.0 bulk index 性能调优实践
elasticsearch5.3.0 bulk index 性能调优实践 通俗易懂
- JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
jvm调优主要针对堆内存,堆内存分为:新生区.养老区和永久区 永久区存放的是系统jdk自身的interface和class的元数据,所以唯有新生区和养老区具有优化空间. 新生区:伊甸区和幸存者区.所有 ...
- Nginx-PHP优化设置 + lnmp调优的关键影响因素 + php-fpm + nginx返回码 + tcp调优 + 最大文件描述符
https://www.cnblogs.com/zengkefu/p/5602473.html最大文件描述符 https://blog.csdn.net/fanren224/article/detai ...
- 性能调优的本质、Spark资源使用原理和调优要点分析
本课主题 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)
性能分析工具jstatjmapjhatjstack 前提概要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jsta ...
- JVM性能调优(3) —— 内存分配和垃圾回收调优
前序文章: JVM性能调优(1) -- JVM内存模型和类加载运行机制 JVM性能调优(2) -- 垃圾回收器和回收策略 一.内存调优的目标 新生代的垃圾回收是比较简单的,Eden区满了无法分配新对象 ...
随机推荐
- windows 设置/修改全局快捷键
打开控制面板,小图表显示下 点击 管理工具项, 将自己想要谁知快捷键的程序的快捷方式放进去,(需要确认管理员权限) 如图,第一个即为 lz添加的 右击选择属性 在快捷键处同时按下你想要的组合键即可(不 ...
- 一篇关于Maven项目的jar包Shell启动脚本
使用Maven作为项目jar包依赖的管理,常常会遇到命令行启动,笔者也是哥菜鸟,在做微服务,以及服务器端开发的过程中,常常会遇到项目的启动需要使用main方法,笔者潜心的研究了很多博客,发现大多写的都 ...
- ngix_http_stub_status_module
1.ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的,所以在编译 Ngin ...
- 大数据 --> 一致性Hash算法
一致性Hash算法 一致性Hash算法(Consistent Hash)
- c++ --> const关键字总结
const关键字总结 C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性.const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变 ...
- Algorithm --> 最长公共子序列(LCS)
一.什么是最长公共子序列 什么是最长公共子序列呢?举个简单的例子吧,一个数列S,若分别是两个或多个已知序列的子序列,且是所有符合条件序列中最长的,则S称为已知序列的最长公共子序列. 举例如 ...
- LAMP平台部署(转)
LAMP平台的概述 LAMP环境脚本部署:https://github.com/spdir/ShellScripts/tree/master/lamp LAMP的介绍:百度百科 LAMP平台的构成组件 ...
- [poj3468]A Simple Problem with Integers_线段树
A Simple Problem with Integers 题目大意:给出n个数,区间加.查询区间和. 注释:1<=n,q<=100,000.(q为操作次数). 想法:嗯...学了这么长 ...
- 课堂测试ch06
课堂测试ch06 下面代码中,对数组x填充后,采用直接映射高速缓存,所有对x和y引用的命中率为(D) A. 1 B. 1/4 C. 1/2 D. 3/4 解析:在填充了之后,对于x和y数组,只有在引用 ...
- 雷云Razer Synapse2.0使用测评 -第二次作业
雷蛇云驱动Razer Synapse2.0使用测评 雷蛇(Razer)是全球顶级游戏设备品牌之一,1998年由CEO Min-Liang Tan和Robert "Razerguy" ...