本课设中需要对STM32的端口进行程序的配置,下为PA口的配置程序, GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7| GPIO_Pin_2 | GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure)
根据指定的参数初始化外设GPIOA寄存器,首先GPIO_InitStructure.GPIO_Pin选择待设置的GPIOA管脚,通过使用操作符“|”一次选中了多个管脚,选择了PA0端口、PA2端口,PA6端口、PA7端口,GPIO_Speed用以设置选中管脚的速率,管脚的速率有三种:10MHz、2MHz和50MHz,由于STM32强大的处理能力,为了能够达系统速率的提高,选择了端口的最高输出速率为50MHz,GPIO_Mode用以设置选中管脚的工作状态。,GPIO 端口有八种工作状态:GPIO_Mode_AIN 模拟输入, GPIO_Mode_IN_FLOATING 浮空输入, GPIO_Mode_IPD 下拉输入, GPIO_Mode_IPU 上拉输入, GPIO_Mode_Out_OD 开漏输出, GPIO_Mode_Out_PP 推挽输出, GPIO_Mode_AF_OD 复用开漏输出, GPIO_Mode_AF_PP 复用推挽输出。由于选择的PA2端口和PA6端口需要产生PWM信号,因此选择了复用推挽输出的工作状态,需要设置注意:当某管脚设置为上拉或者下拉输入模式,使用寄存器Px_BSRR和PxBRR 。GPIO_Mode允许同时设置GPIO方向(输入/输出)和对应的输入/输出设置。 当I/O端口被配置为输出时: (1) 输出缓冲器被激活 ─ 开漏模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将端口置于高阻状态(P-MOS从不被激活)。 ─ 推挽模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将激活P-MOS。 (2)施密特触发输入被激活 (3) 弱上拉和下拉电阻被禁止 (4) 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器 (5) 在开漏模式时,对输入数据寄存器的读访问可得到I/O状态 (6) 在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。
4.5.2A/D转换程序设计
在开始ADC转换和14个时钟周期后,EOC标志被设置,16位ADC数据寄存
26
器包含转换的结果,ADC在开始精确转换前需要一个稳定时间TSTAB。时序图如下图,
图4.9 时序图
在ADC初始化设置时,首先开启AHB外设时钟使能寄存器DMA1时钟,定义转换数据量,设置DMA的通道1的初始化,独立地选择通道的采样时间,在通道1设置看门狗,开启ADC1并启动转换,应用连续转换模式,使用DMA模式,接着便开始转换规则通道,完成由模拟量到数据量的转变。 void adc_Init (void) {
// GPIOA->CRL &= ~0x0000000F; /* set PIN1 analog input (see stm32_Init.c) */
RCC->AHBENR |= (1<<0); /* enable peripheral clock for DMA */
27
DMA1_Channel1->CMAR = (unsigned long)&analog; /* set chn1 memory address */
DMA1_Channel1->CPAR = (unsigned long)&(ADC1->DR); /* set chn1 peripheral address */
DMA1_Channel1->CNDTR = 3; /* transmit 3 words */
// DMA1_Channel1->CCR = 0x00002520; /* configure DMA channel 1 */
DMA1_Channel1->CCR = 0x000025A0; /* configure DMA channel 1 */
/* circular mode, memory increment mode */
/* memory & peripheral size 16bit */
/* channel priotity high */
DMA1_Channel1->CCR |= (1 << 0); /* enable DMA Channe1 */
RCC->APB2ENR |= (1<<9); /* enable periperal clock for ADC1 */
ADC1->SQR1 = 0x00200000; /* three conversions */
ADC1->SQR3 = (3<<10) | (2<<5) | (1<<0); /* set order to chn1 - chn2 - chn3 */
ADC1->SMPR2 = (5<< 9) | (5<<6) | (5<<3); /* set sample time (55,5 cycles) */
28
ADC1->CR1 = 0x00000100; /* use independant mode, SCAN mode */
ADC1->CR2 = 0x000E0103; /* data align right, cont. conversion */
/* EXTSEL = SWSTART */
/* enable ADC, DMA mode */
ADC1->CR2 |= 0x00500000; /* start SW conversion */ }
4.5.3 PWM细分程序设计
脉冲宽度调制(PWM)是英文“Pulse Width Modulation”的缩写,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量,通信,功率控制与变换等许多领域。实现STM32定时器的PWM信号的产生的子程序如下,
#include \struct Motor2P_Table { //细分表结构
unsigned char mQuadrant; //象限0-3 unsigned char mX_Pwm; //x 输出的PWM unsigned char mY_Pwm; //y 输出的PWM };
struct Motor2P{
unsigned char mTableId; //细分表ID
unsigned char mTask; //马达驱动的任务转移号
unsigned char mSaveTimer; //马达驱动节电模式使用的计数器 unsigned char mReg; //马达驱动使用的寄存器
29
unsigned char mTimer; //对2MS 的计数器,时间扩展 unsigned int mSteps; //马达要走的步数 unsigned char mDirect; //马达走动方向
unsigned char mStepRunTimer; //步进时输出有效的时间寄存器 unsigned char mStepIdleTimer; //步进时输出节电的时间寄存器 unsigned char mStepCount; //细分表走动步长。1-2-4-8-16 };
#define Motor2P_Head
Motor2P_Head struct Motor2P sMotor2P; //定义变量 #define Motor2P_Head #define Step_Quadrant0 0 #define Step_Quadrant1 1 #define Step_Quadrant2 2 #define Step_Quadrant3 3
//0-90 度的细分的PWM 数据(0-255).n 是细分=16.x=cos(a)*255,y=a/tg(a)(正弦转多边,减少误差).逆时针表,半周期。 const struct Motor2P_Table cMotor2P_Table[]=
程序定义了细分表结构体,包含了四个象限,X轴输出的PWM和Y轴输出的PWM。struct Motor2P定义了步进电机的结构体包括细分表ID、马达走动方向、细分表走动步长等。#define Motor2P_Head定义了步进电机的变量及四个象限。
4.5.4电机控制程序设计
通过A/D读取数值,转换为-180—180数值。如果转换值大于0,则步进电机正转,否则步进电机反转。如果转换值大于170,则步进电机最大速度正转。如果转换值小于-170,则步进电机最大速度反转。如果读取的A/D转换值与显示的值一样,则继续读取A/D值。如果读取值与显示值不一样,则重新计算显示。
ad_value=-180+analog[0] * 360 / 0xFFF; if(ad_value>0) run_dir=1; else run_dir=0;
30