This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

基于TM4C123x的 直流电机速率控制与测量实验程序解析



// 直流电机速率控制与测量实验程序解析

//头文件
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include "utils/ustdlib.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "grlib/grlib.h"
#include "drivers/buttons.h"
#include "drivers/cfal96x64x16.h"

//宏定义以及静态变量定义
//一个PWM脉冲时间所占的时钟周期数
#define PWM_MAX 400			
#define PWM_MIN 0

//每秒systick的次数,对应于计算电机速度的次数//
#define TICKS_PER_SECOND 2	
static volatile ui32 TickCount = 0;  //用于计数systick
static char cText[10];						  //OLED显示内容
static ui32 motor_signal = 0;		 //电机计数信号

//主程序
int main (void)
{
FPUEnable();
FPULazyStackingEnable();

//系统时钟设置
SysCtlClockSet(SYSCTL_SYSDIV_6 |SYSCTL_USE_PLL \ 
|SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);   

//外围设备初始化
ButtonsInit();	      //按键初始化
CFAL96x64x16Init();  //OLED显示初始化
GrContextInit(&sContext, &g_sCFAL96x64x16);
……
//GPIO口PN0作为脉冲1信号的输入
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
ROM_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE,GPIO_PIN_0);

//设置systick为每秒两次,即每半秒脉冲1计数清0,更新电机速度。
ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / TICKS_PER_SECOND);
ROM_SysTickEnable();
ROM_SysTickIntEnable();	

 //PWM设置
//使能GPIO口PORT G
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);	
//使能PWM 
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);	
// PWM时钟配置:不分频
ROM_SysCtlPWMClockSet(SYSCTL_PWMDIV_1);	
//设置PG7为PWM模式0,信号PWM7
ROM_GPIOPinConfigure(GPIO_PG7_M0PWM7);	
//设置PWM发生器3,减计数,非同步
ROM_GPIOPinTypePWM(GPIO_PORTG_BASE,GPIO_PIN_7); 
ROM_PWMGenConfigure(PWM_BASE, PWM_GEN_3,
    //设置PWM脉冲占时钟的周期数
    PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
 //设置占空比,初始为250/400=62.5% 
ROM_PWMGenPeriodSet(PWM_BASE, PWM_GEN_3, PWM_MAX); 
ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_7, PWM_Width);
//使能PWM发生器3
ROM_PWMGenEnable(PWM_BASE, PWM_GEN_3);	      
//产生PWM波
ROM_PWMOutputState(PWM_BASE,  PWM_OUT_7_BIT, true);	 

//码盘计数以及速度按键控制
while(1)
	{
		//等待下一次tick       
		while(LastTickCount == TickCount)
		{
			ui8 ucButtonState;
			ui8 ucButtonChanged;
			ucButtonState = ButtonsPoll(&ucButtonChanged, 0);
//如果按键UP,增加PWM的占空比
if(BUTTON_PRESSED(UP_BUTTON, ucButtonState, ucButtonChanged))  

			{
			    PWM_Width = PWM_Width+5;
			    if(PWM_Width > PWM_MAX)
			    	PWM_Width = PWM_MAX;
			    ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_7, PWM_Width);
			}
//如果按键DOWN,减小PWM的占空比
    if(BUTTON_PRESSED(DOWN_BUTTON, ucButtonState, ucButtonChanged)) 

			{
				PWM_Width = PWM_Width-5;
				if(PWM_Width < PWM_MIN)
					PWM_Width = PWM_MIN;
				ROM_PWMPulseWidthSet(PWM_BASE, PWM_OUT_7, 
PWM_Width);
			}
//当读入的计数脉冲信号没有翻转时,始终读取该信号
			while(motor_signal!=status) 
			{
motor_signal=
ROM_GPIOPinRead(GPIO_PORTN_BASE,GPIO_PIN_0);
			}
//若信号翻转,则计数加1,同时改变status为当前状态值,等待下
//一次翻转,这样得以保证每一个上升沿和下降沿都被计数。
			cnt = cnt+1;
			status = 1-status;
}
//每半秒钟计数清0
cnt = 0 ;					    
//更新TickCount 
LastTickCount = TickCount;	

//速度计算和显示
ROM_SysTickDisable();
cnt = cnt*60/334;				//计算每分钟转速
usprintf(cText,"%10d",cnt);		//送OLED显示
GrContextForegroundSet(&sContext, ClrWhite);
GrStringDrawCentered(&sContext,cText, -1,
			GrContextDpyWidthGet(&sContext) / 3*2,
			((GrContextDpyHeightGet(&sContext) - 24) / 2) + 24, 1);
		    GrFlush(&sContext);
//计算占空比并显示		
unsigned int rate = 100*PWM_Width/PWM_MAX;
usprintf(cText,"%4u%%",rate);
GrContextForegroundSet(&sContext, ClrWhite);
GrStringDrawCentered(&sContext,cText, -1,
			GrContextDpyWidthGet(&sContext) /3,
((GrContextDpyHeightGet(&sContext) - 24) / 2) + 24, 1);
GrFlush(&sContext);
ROM_SysTickEnable();
//为了使得脉冲计数更准确,此处屏蔽了SysTick,以避免由于处理该段程
//序对实际计数时间造成的影响