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区满了无法分配新对象 ...
随机推荐
- 有序的Map集合--LinkedHashMap
提出问题: 在写一个dao的时候,我的需求是这个dao是一个万能的,目前的方法只有一个查询出实体类对应的表中所有的数据,通过传入的对象,利用反射获取实体类中的属性名,属性类型,利用字符串拼接获取相应属 ...
- 用bat文件启动mongodb
bat文件是dos下的批处理文件.批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用cm ...
- poj 3664
http://poj.org/problem?id=3664 进行两轮选举,第一轮选前n进入第二轮,第二轮选最高 #include<algorithm> #include<cstdi ...
- flex布局简析
最近开始对flex布局进行一个重新的认识. 首先. flex布局适用于所有元素 但是注意一点的就是,一旦父级元素设定flex布局的时候,子元素的传统布局属性, float,clear,vertical ...
- python安装的时候报SSL连接错误的解决办法
Collecting xlwt Could not fetch URL https://pypi.python.org/simple/xlwt/: There was a problem conf ...
- java操作数据库的通用的类
package cn.dao; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; ...
- NVL2 这个函数,
NVL2(expr1,expr2,expr3) 如果参数表达式expr1值为NULL,则NVL2()函数返回参数表达式expr3的值:如果参数表达式expr1值不为NULL,则NVL2()函数 ...
- Spring Boot + Freemarker多语言国际化的实现
最近在写一些Web的东西,技术上采用了Spring Boot + Bootstrap + jQuery + Freemarker.过程中查了大量的资料,也感受到了前端技术的分裂,每种东西都有N种实现, ...
- CentOS 6.5 通过命令行安装发送邮件
1.安装sendmail: yum install sendmail 2.安装mailx: yum install mailx -y 3.编辑发送的配置文件: vi /etc/mail.rc #在最后 ...
- Git忽略规则.gitignore梳理
对于经常使用Git的朋友来说,.gitignore配置一定不会陌生.废话不说多了,接下来就来说说这个.gitignore的使用. 首先要强调一点,这个文件的完整文件名就是".gitignor ...