基于arm的pwm波参数测试本科论文.docx
- 文档编号:10964341
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:27
- 大小:351.59KB
基于arm的pwm波参数测试本科论文.docx
《基于arm的pwm波参数测试本科论文.docx》由会员分享,可在线阅读,更多相关《基于arm的pwm波参数测试本科论文.docx(27页珍藏版)》请在冰豆网上搜索。
基于arm的pwm波参数测试本科论文
基于ARM的PWM波参数测试仪
摘要:
随着电子技术的发展PWM应用领域包括测量,通信,功率控制与变换,电动机控制、伺服控制、甚至某些音频放大器,因此研究PWM技术具有十分重要的现实意义。
本文是设计频率/脉冲宽度的测量与显示的硬件电路与程序的编制。
它可以测量脉冲信号的脉冲宽度,频率等参数。
利用STM32通用定时器TIME4产生PWM波。
利用定时器TIME3输入捕获模式来测量由PA7输入的脉冲信号的频率,占空比,电压。
关键字:
STM32PWM占空比输入捕获模式频率电压
1总体设计
本设计旨在加深对ARM的学习,巩固大学四年所学专业知识,提升动手能力和思考问题解决问题的能力。
本设计选择意法半导体的STM32F开发板,通过对该开发板的研究学习,和对STM32F103系列芯片的学习,掌握其各种外设功能。
通过对TIM4定时器进行控制,使之各通道输出插入死区的互补PWM输出,各通道输出频率均为10KHz。
其中,通道3输出的占空比为50%,通道4输出的占空比为35%,各通道互补输出为反相输出。
TIM4定时器的通道3到4的输出分别对应PB6和PB7引脚。
然后利用TM3的通道2进行捕获,通道2所接是PA7管脚,根据捕获的高低电平的计数可以算出其频率和占空比,启动AD对PA7进行采集,所测得的电压为其峰值电压。
最后用串口在电脑上显示出测得的电压,占空比,频率。
1.1程序流程图
整个设计程序流程如图1所示:
否
是
否
是
图1程序流程图
2详细设计
2.1STM32简介
STM32F103xx增强型系列使用高性能的ARM/Cortex-M3/32位的RISC内核,工作频率为72MHz,内置高速存储器(高达128K字节的闪存和20K字节的SRAM),丰富的增强I/O端口和联接到两条APB总线的外设。
所有型号的器件都包含2个12位的ADC、3个通用16位定时器和一个PWM定时器,还包含标准和先进的通信接口:
多达2个I2C和SPI、3个USART、一个USB和一个CAN。
STM32F103xx增强型系列工作于-40℃至+105℃的温度范围,供电电压2.0V至3.6V,一系列的省电模式保证低功耗应用的要求。
完整的STM32F103xx增强型系列产品包括从36脚至100脚的五种不同封装形式;根据不同的封装形式,器件中的外设配置不尽相同。
下面给出了该系列产品中所有外设的基本介绍。
这些丰富的外设配置,使得STM32F103xx增强型微控制器适合于多种应用场合:
·电机驱动和应用控制;
·医疗和手持设备;
·PC外设和GPS平台;
·工业应用:
可编程控制器、变频器、打印机和扫描仪;
·警报系统,视频对讲,和暖气通风空调系统;
2.2STM32F103RBT6管脚图
芯片引脚图如图1.1:
图2STM32F103RBT6管脚图
2.2内部资源
STM32有丰富的内部资源,如下所示:
·RealViewMDK(MiertocontrollerDevelopmentKit)基于ARM微控制器的专业嵌入式开发工具;
·内置闪存存储器;
·内置SRAM;
·嵌套的向量式中断控制器(NVIC);
·外部中断/事件控制器(EXTI);
·时钟和启动;
·自举模式;
·DMA;
·RTC(实时时钟)和后备寄存器;
·窗口看门狗;
·I2C总线;
·通用同步/异步接受发送器(USART);
·串行外设接口(SPI);
·控制器区域网络(CAN);
·通用串行总线(USB);
·通用输入输出接口(GPIO);
·ADC(模拟/数字转换器);
·温度传感器;
·串行线JTAG调试口(SWJ-DP)。
STM32F103xx增强型系列产品中内置了多达3个同步的标准定时器。
每个定时器都有一个16位的自动加载递加/递减计数器、一个16位的预分频器和4个独立的通道,每个通道都可用于输入捕获、输出比较、PWM和单脉冲模式输出,在最大的封装配置中可提供最多12个输入捕获、输出比较或PWM通道。
它们还能通过定时器链接功能与高级控制定时器共同工作,提供同步或事件链接功能。
在调试模式下,计数器可以被冻结。
任一个标准定时器都能用于产生PWM输出。
每个定时器都有独立的DMA请求机制。
2.3串口通信部分
该部分的主要功能是将测的数值传到计算机中显示,首先要配置串口的工作模式,选择USART1串口,该串口默认的收发管脚是PA9,PA10;由于在调试过程中发现如果波特率过高会出现乱码现象,所以把波特率设为9200。
在该部分写了一个printf格式输出函数。
程序部分源代码如下:
voidUSART1_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
USART_InitTypeDefUSART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}
intfputc(intch,FILE*f)
{
USART_SendData(USART1,(unsignedchar)ch);
while(!
(USART1->SR&USART_FLAG_TXE));
return(ch);
}
staticchar*itoa(intvalue,char*string,intradix)
{
inti,d;
intflag=0;
char*ptr=string;
if(radix!
=10)
{
*ptr=0;
returnstring;
}
if(!
value)
{
*ptr++=0x30;
*ptr=0;
returnstring;
}
if(value<0)
{
*ptr++='-';
value*=-1;
}
for(i=10000;i>0;i/=10)
{
d=value/i;
if(d||flag)
{
*ptr++=(char)(d+0x30);
value-=(d*i);
flag=1;
}
}
*ptr=0;
returnstring;
}
voidUSART1_printf(USART_TypeDef*USARTx,uint8_t*Data,...)
{
constchar*s;
intd;
charbuf[16];
va_listap;
va_start(ap,Data);
while(*Data!
=0)//判断是否到达字符串结束符
{
if(*Data==0x5c)//'\'
{
switch(*++Data)
{
case'r':
//回车符
USART_SendData(USARTx,0x0d);
Data++;
break;
case'n':
//换行符
USART_SendData(USARTx,0x0a);
Data++;
break;
default:
Data++;
break;
}
}
elseif(*Data=='%')
{//
switch(*++Data)
{
case's':
//字符串
s=va_arg(ap,constchar*);
for(;*s;s++)
{
USART_SendData(USARTx,*s);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
Data++;
break;
case'd':
//十进制
d=va_arg(ap,int);
itoa(d,buf,10);
for(s=buf;*s;s++)
{
USART_SendData(USARTx,*s);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
Data++;
break;
default:
Data++;
break;
}
}/*endofelseif*/
elseUSART_SendData(USARTx,*Data++);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
}
2.4PWM输出实现
该设计对TIM4定时器进行控制,输出PWM波,各通道输出频率均为10KHz。
把PB6,PB7设为下拉模式。
其中通道1输出的占空比为50%,通道2输出的占空比为34.5%,各通道互补输出为反相输出。
TIM4定时器的通道1到2的输出分别对应PB6,PB7引脚,脚在开发板上已经以插针形式引出。
由于TIM4计数器的时钟频率为72MHz,各通道输出频率fTIM4为10KHz,根据:
fTIM4=TIM4CLK/(TIM4_Period+1),可得到TIM4预分频器的TIM4_Period为7199。
根据通道输出占空比TIM4_CCRx/(TIM4_Period+1),可以得到各通道比较/捕获寄存器的计数值。
其中:
TIM4_CCR1寄存器的值3600、TIM4_CCR2寄存器的值为2520。
程序部分原代码:
staticvoidTIM4_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
staticvoidTIM4_Mode_Config(void)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
TIM_OCInitTypeDefTIM_OCInitStructure;
u16CCR1_Val=3600;
u16CCR2_Val=2520;
TIM_TimeBaseStructure.TIM_Period=7199;//当定时器从0计数到999,即为1000次,为一个定时周期
TIM_TimeBaseStructure.TIM_Prescaler=0;//设置预分频:
不预分频,即为72MHz
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分频系数:
不分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=CCR1_Val;//设置跳变值,当计数器计数到这个值时,电平发生跳变
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//当定时器计数值小于CCR1_Val时为高电平
TIM_OC1Init(TIM4,&TIM_OCInitStructure);//使能通道1
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=CCR2_Val;//设置通道2的电平跳变值,输出另外一个占空比的PWM
TIM_OC2Init(TIM4,&TIM_OCInitStructure);//使能通道2
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4,ENABLE);//使能TIM3重载寄存器ARR
TIM_Cmd(TIM4,ENABLE);//使能定时器3
}
2.4AD采集电路
本设计采用AC1的通道7来进行AD转换,其详细设置步骤如下:
1.PA口时钟,设置PA7为下拉输入。
STM32F103RBT6的ADC通道7在PA7上,所以,我们先要使能PORTA的时钟,然后设置PA7为下拉输入。
2.能ADC1时钟,并设置分频因子。
要使用ADC1,第一步就是要使能ADC1的时钟,在使能完时钟之后,进行一次ADC1的复位。
接着我们就可以通过RCC_CFGR设置ADC1的分频因子。
分频因子要确保ADC1的时钟(ADCCLK)不要超过14Mhz。
3.置ADC1的工作模式。
在设置完分频因子之后,我们就可以开始ADC1的模式配置了,设置单次转换模式、触发方式选择、数据对齐方式等都在这一步实现。
4.置ADC1规则序列的相关信息。
接下来我们要设置规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为1,然后设置通道0的采样周期。
5.启AD转换器,并校准。
在设置完了以上信息后,我们就开启AD转换器,执行复位校准和AD校准,注意这两步是必须的!
不校准将导致结果很不准确。
6.取ADC值。
在上面的校准完成之后,ADC就算准备好了。
接下来我们要做的就是设置规则序列0里面的通道,然后启动ADC转换。
在转换结束后,读取ADC1_DR里面的值就是了。
通过以上几个步骤的设置,我们就可以正常的使用STM32的ADC1来执行AD转换操作了。
程序部分源代码如下:
staticvoidADC1_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;//PA0设置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//PA0输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.0
GPIO_ResetBits(GPIOA,GPIO_Pin_7);//PC1,输入时不用设置速率
}
staticvoidADC1_Mode_Config(void)
{
DMA_InitTypeDefDMA_InitStructure;
ADC_InitTypeDefADC_InitStructure;
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr=ADC1_DR_Address;//ADC地址
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADC_ConvertedValue;//内存地址
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize=1;
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址固定
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Disable;//内存地址固定
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//半字
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//循环传输
DMA_InitStructure.DMA_Priority=DMA_Priority_High;
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
DMA_Init(DMA1_Channel1,&DMA_InitStructure);
DMA_Cmd(DMA1_Channel1,ENABLE)
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立ADC模式
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//禁止扫描模式,扫描模式用于多通道采集
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换模式,即不停地进行ADC转换
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//不使用外部触发转换
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//采集数据右对齐
ADC_InitStructure.ADC_NbrOfChannel=1;//要转换的通道数目1
ADC_Init(ADC1,&ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_RegularChannelConfig(ADC1,ADC_Channel_7,1,ADC_SampleTime_55Cycles5);
ADC_DMACmd(ADC1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
2.5PWM输入捕获模式
PWM输入捕获模式是输入捕获模式的特例,自己理解如下
1.每个定时器有四个输入捕获通道IC1、IC2、IC3、IC4。
且IC1IC2一组,IC3IC4一组。
并且可是设置管脚和寄存器的对应关系。
2.同一个TIx输入映射了两个ICx信号。
3.这两个ICx信号分别在相反的极性边沿有效。
4.两个边沿信号中的一个被选为触发信号,并且从模式控制器被设置成复位模式。
5.当触发信号来临时,被设置成触发输入信号的捕获寄存器,捕获“一个PWM周期(即连续的两个上升沿或下降沿)”,它等于包含TIM时钟周期的个数(即捕获寄存器中捕获的为TIM的计数个数n)。
6.同样另一个捕获通道捕获触发信号和下一个相反极性的边沿信号的计数个数m,即(即高电平的周期或低电平的周期)
7.由此可以计算出PWM的时钟周期和占空比了
frequen
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 arm pwm 参数 测试 本科 论文