嵌入式系统实践 07 ——基于ARM汇编 Keil5 MSP432 P401R开发板

该代码示例展示了如何在MSP432p4xx微控制器上使用定时器进行中断设置,同时模拟交通信号灯的红绿黄灯切换。通过设置DCO频率和Timer32模块,实现了不同时间间隔的中断事件,用于控制GPIO端口的输出,从而控制信号灯的状态。此外,还包括了按键中断处理,用于切换信号灯模式。

lab 7

定时器并行

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>

int main(void)
{    
    MAP_WDT_A_holdTimer();/* 停用开门狗 */
    
    //Simple FPU Config
    MAP_FPU_enableModule();/*启用FPU加快DCO频率计算,注:DCO是内部数字控制振荡器,默认是3M频率*/    
    // MAP_CS_setDCOFrequency(10000000);/* 设置DCO频率为指定频率,此处DCO=10M*/
    //Simple FPU Config
        
	//02要求:设置为DCO=1M,去掉一个0
		MAP_CS_setDCOFrequency(1000000);
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);/*设置MCLK(主时钟频率),MCLK=DCO频率/时钟分频系数,此处MCLK=DCO=10M*/
        
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);/* 配置P1.0为输出模式 */
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0);/*拉高P1.0引脚电压*/
    
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);/* 配置P2.1为输出模式 */
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);/*拉高P2.1引脚电压*/
            
    /* 配置Timer32的第一个计数器为32位模式,周期模式,定时器频率=MCLK/定时器分频系数 此处第一个计数器频率=MCLK=10M */
    MAP_Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT,TIMER32_PERIODIC_MODE);
    
    /* 配置Timer32的第二个计数器为32位模式,周期模式,定时器频率=MCLK/定时器分频系数 此处第二个计数器频率=MCLK=10M */
    MAP_Timer32_initModule(TIMER32_1_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT,TIMER32_PERIODIC_MODE);
    
    /* 使能Timer32第一个计数器中断开关*/
    MAP_Interrupt_enableInterrupt(INT_T32_INT1);    
    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);

    /* 使能Timer32第二个计数器中断开关*/
    MAP_Interrupt_enableInterrupt(INT_T32_INT2);    
    MAP_Timer32_enableInterrupt(TIMER32_1_BASE);
    
    MAP_Interrupt_enableMaster();/*使能中断总开关*/
    
    //MAP_Timer32_setCount(TIMER32_0_BASE,20000000); /*设置Timer32第一个计数器计数周期,此处 20M/10M=2s*/    
    //MAP_Timer32_setCount(TIMER32_1_BASE,2000000); /*设置Timer32第二个计数器计数周期,此处 2M/10M=0.2s*/    
    
		MAP_Timer32_setCount(TIMER32_0_BASE,4000000); /*第一个学号为4,此处 4M/1M=4s*/    
    MAP_Timer32_setCount(TIMER32_1_BASE,4000000); /*第2个学号为4,此处 4M/1M=4s*/    
		
    MAP_Timer32_startTimer(TIMER32_0_BASE, false);/*Timer32第一个计数器以周期性模式开始计数*/
    MAP_Timer32_startTimer(TIMER32_1_BASE, false);/*Timer32第二个计数器以周期性模式开始计数*/
    
    /*打结,因无其他操作,此处为空循环*/
    while(1); 
}

/* Timer32第一个计数器中断函数*/
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE); /*清除Timer32第一个计数器中断标志*/  
    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0); /*翻转P1.0的电平*/
}

/* Timer32第二个计数器中断函数*/
void T32_INT2_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_1_BASE); /*清除Timer32第二个计数器中断标志*/  
    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2,GPIO_PIN1); /*翻转P2.1的电平*/
}

交通信号灯模拟

#include <string.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

#define COUNT (25000) //空循环时间=COUNT/CPU主频,此处大致为25K/1M=25ms

/*
(GPIO_PORT_P1, GPIO_PIN0) 红灯

(GPIO_PORT_P2, GPIO_PIN0) 红灯
(GPIO_PORT_P2, GPIO_PIN1) 绿灯
(GPIO_PORT_P2, GPIO_PIN2) 蓝灯
*/

typedef enum
{
    DETECT = 0,
    S1,
    S2,
    S1S2
} KEY_STATUS;

KEY_STATUS key = DETECT; /*DETECT时为按键检测状态,S1为S1键按下,S2为S2键按下,S1S2为S1和S2同时按下*/
int time = COUNT;
int cnt = 0;
int choose = 0;
int flag = 0;

int main(void)
{
    MAP_WDT_A_holdTimer(); /* 停用看门狗定时器 */

    //Simple FPU Config
    MAP_FPU_enableModule();          /*启用FPU加快DCO频率计算,注:DCO是内部数字控制振荡器,默认是3M频率*/
    MAP_CS_setDCOFrequency(1000000); /* 设置DCO频率为指定频率,此处DCO=1M*/

    GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);
    /* 配置Timer32的第一个计数器为32位模式,周期模式,定时器频率=MCLK/定时器分频系数 此处第一个计数器频率=MCLK=1M */
    MAP_Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);

    /* 使能Timer32第一个计数器中断开关*/
    MAP_Interrupt_enableInterrupt(INT_T32_INT1);
    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);

    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1); //设置P1.1(s1按键)为输入模式并拉高
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);                 //使能GPIO1.1中断
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);              //清除P1.1中断

    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN4); //设置P1.4(s2按键)为输入模式并拉高
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4);                 //使能GPIO1.4中断
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN4);              //清除P1.1中断
    MAP_Interrupt_enableInterrupt(INT_PORT1);                          //使能PORT1中断

    //配置红灯
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);    //设置P2.0为输出模式
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0); //使红色灯初始为低电平(常暗)

    //配置黄灯
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);    //设置P2.0为输出模式
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0); //使LED2中红色灯初始为低电平(常暗)
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);    //设置P2.1为输出模式
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1); //使LED2中绿色灯初始为低电平(常暗)

    //配置绿灯
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);    //设置P2.1为输出模式
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1); //使绿色灯初始为低电平(常暗)

    GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1); //绿色灯亮
    MAP_Timer32_setCount(TIMER32_0_BASE, 5000000); /*设置Timer32第一个计数器计数周期,5s*/ 
    MAP_Timer32_startTimer(TIMER32_0_BASE, false); /*Timer32第一个计数器以周期性模式开始计数*/
    MAP_Interrupt_enableMaster();                     //开启中断总开关

    /*主函数用于按键检测,以后要添加其他操作要根据具体情况修改代码*/
    while (1)
    {
        if (key == DETECT)
        {
            while (time--) //此处为按键消抖
            {
                if (key == S1S2)
                    break; //如果在25ms内有按键响应,那么就是双击
                /*可在此处添加其他操作,但要根据具体情况修改代码*/
            }
            time = COUNT; /*设置25ms左右的按键检测时间*/
        }
        //上面代码只是用来消除噪声
        else
        {
            if (key == S1S2)//再次进入循环模式
            {                                                    
                choose = 0;//下一个状态:黄灯
                MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
								//点亮绿灯,设置定时器为5s(开始)
								GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);  //红灯灭
                GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1); //绿灯亮 
                MAP_Timer32_setCount(TIMER32_0_BASE, 5000000); /*设置Timer32第一个计数器计数周期,此处 5M/1M=5s*/
                MAP_Timer32_startTimer(TIMER32_0_BASE, false); /*Timer32第一个计数器以周期性模式开始计数*/
								//以上为友情提示(结束)
                MAP_Timer32_enableInterrupt(TIMER32_0_BASE);//使能Timer32第一个计数器中断
            }
            else if (key == S2)//通行模式
						{//请书写自己的代码
               Timer32_disableInterrupt(TIMER32_0_BASE);  
							GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
							GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);
              //MAP_Timer32_disableInterrupt(TIMER32_0_BASE);     
							//禁用Timer32第一个计数器,也可以通过状态值控制定时器
            }
            else if (key == S1)//禁行模式
            {//请书写自己的代码
               Timer32_disableInterrupt(TIMER32_0_BASE);  
							GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
							GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0);                                                              
            }

            key = DETECT; //恢复到按键检测状态
        }
    }
}

/*
void myDelay(unsigned int cnt)
{
	unsigned int i = 1000 * cnt;
	while(i--);
	return;
}*/

/* Timer32第一个计数器中断函数*/
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE); /*清除Timer32第一个计数器中断标志*/
    if (choose == 0)//黄灯1.5秒
    {//请书写自己的代码
			MAP_Timer32_setCount(TIMER32_0_BASE, 1500000); 
      MAP_Timer32_startTimer(TIMER32_0_BASE, false); /*Timer32第一个计数器以周期性模式开始计数*/
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
				GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1);    
			//MAP_Timer32_setCount(TIMER32_0_BASE, 3500000); 
			//GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
    }
    if (choose == 1)//红灯2.5秒
    {//请书写自己的代码
			MAP_Timer32_setCount(TIMER32_0_BASE, 2500000); 
      MAP_Timer32_startTimer(TIMER32_0_BASE, false); /*Timer32第一个计数器以周期性模式开始计数*/
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
				GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0);    
			//MAP_Timer32_setCount(TIMER32_0_BASE, 2500000); 
			//GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
				//myDelay(25);
    }
    if (choose == 2)//绿灯5秒
    {//请书写自己的代码
			MAP_Timer32_setCount(TIMER32_0_BASE, 5000000); 
      MAP_Timer32_startTimer(TIMER32_0_BASE, false); /*Timer32第一个计数器以周期性模式开始计数*/
				GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
				GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);    
				//myDelay(50);
        
    }
    choose = (choose + 1) % 3;//用于循环的改变状态
}

void PORT1_IRQHandler(void) //按键中断,检测到按键按下更新状态为S1,S2,S1S2
{
    uint32_t status;

    status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

    if ((status & GPIO_PIN1) && (status & GPIO_PIN4))
    {
        key = S1S2;
    }
    else if (status & GPIO_PIN1)
    {
        if (key == DETECT)
        {
            key = S1;
            time = COUNT;
        }
        else if (key == S2)
            key = S1S2;
    }
    else if (status & GPIO_PIN4) //S2键短按下
    {
        if (key == DETECT) //若之前为按键检测状态
        {
            key = S2;
            time = COUNT; //主函数会继续在指定时间检测,若该时间内未有按键按下,则开始执行对应按键的操作。
        }
        else if (key == S1) //若S1键已经按下过,则状态更新为S1S2
            key = S1S2;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值