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

lab 9

熟悉串口工具

使用串口工具打开LaunchPad开发板XDS110 Class Application/User UART串口,串口配置参数:波特率为9600,8位数据位,无校验位,1位停止位,无流量控制;
在串口工具中发送数字“1”,则红灯被点亮;发送数字“2”,则绿灯被点亮;发送数字“3”,则蓝灯被点亮;发送其他ASCII字符,则RGB灯被熄灭。

///******************************************************************************
// *
// *               MSP432P401
// *             -----------------
// *            |                 |
// *            |                 |
// *            |                 |
// *       RST -|     P1.3/UCA0TXD|----> PC 
// *            |                 |
// *            |                 |
// *            |     P1.2/UCA0RXD|<---- PC
// *            |                 |
// *
// *******************************************************************************/
/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

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

/*
http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
*/
const eUSCI_UART_Config uartConfig =
{
        EUSCI_A_UART_CLOCKSOURCE_SMCLK,          //选用SMCLK(1M)时钟源
        6,                                       // BRDIV = 6 ,clockPrescalar时钟分频系数 
        8,                                       // UCxBRF = 8  firstModReg (BRDIV、UCxBRF、 UCxBRS和SMCLK,用于设置串口波特率)
        17,                                      // UCxBRS = 17 secondModReg
        EUSCI_A_UART_NO_PARITY,                  // 校验位None
        EUSCI_A_UART_LSB_FIRST,                  // 低位优先,小端模式
        EUSCI_A_UART_ONE_STOP_BIT,               // 停止位1位
        EUSCI_A_UART_MODE,                       // UART mode
        EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // 设置为过采样,该数值为1
};

int main(void)
{  
    /* 停用开门狗 */
    MAP_WDT_A_holdTimer();
    
    //![Simple FPU Config]   
    MAP_FPU_enableModule();/*启用FPU加快DCO频率计算,注:DCO是内部数字控制振荡器,默认是3M频率*/    
    MAP_CS_setDCOFrequency(4000000);/* 设置DCO频率为指定频率,此处DCO=4M*/
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);/*设置MCLK(主时钟,可用于CPU主频等),MCLK=DCO频率/时钟分频系数,此处MCLK=DCO=4M*/
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);/*设置HSMCLK(子系统主时钟),HSMCLK=DCO频率/时钟分频系数,此处HSMCLK=DCO/4=1M*/
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);/*设置SMCLK(低速子系统主时钟,可用TimerA频率),SMCLK=DCO频率/时钟分频系数,此处SMCLK=DCO/4=1M*/    
    //![Simple FPU Config]

    /* 选用P1.2和P1.3使用UART模式 */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
    /* 使用uartConfig配置UART_A0 */
    MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);

    /* 使能UART_A0 */
    MAP_UART_enableModule(EUSCI_A0_BASE);
    
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); /*使能UART_A0串口接收中断*/ 
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0); /*使能UART_A0中断*/  
    MAP_Interrupt_enableMaster();  /*使能中断总开关*/    
    //红灯
    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_PIN2);    //设置P2.2为输出模式
    GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN2); //使LED2中蓝色灯初始为低电平(常暗)		
    while(1);
}

/*UART_A0中断函数*/
void EUSCIA0_IRQHandler(void)
{
	
		char temp;
    int i=0;        
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); /*将UART_A0中断标志位的值赋值给status*/
    MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);/*清空UART_A0中断标志位*/
	
    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) /*判断是否为UART_A0接受中断*/
    {          
        temp=MAP_UART_receiveData(EUSCI_A0_BASE);
            if(temp == '1')
            {
                GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
                GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0);
                    //写代码控制led
            }
            else if(temp == '2')
            {
                GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
                GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);
                    //写代码控制led
            }
            else if(temp == '3')
            {
                GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
                GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN2);
                    //写代码控制led
            }else{
                GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
                    //写代码控制led 	
            }
            MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
    }   
}
最低要求:打开工程09_03使用串口工具打开LaunchPad开发板XDS110 Class Application/User UART串口,串口配置参数:波特率为96008位数据位,无校验位,1位停止位,无流量控制;从任意起始时间开始以hh:mm:ss(24小时制,时分秒)格式进行计时并通过串口打印当前时间(11次)。
进阶要求:提供串口命令来设置时分秒的初始值,完成设置后使用串口发送g(go)命令开始计时。

串口时钟

///******************************************************************************
// *
// *               MSP432P401
// *             -----------------
// *            |                 |
// *            |                 |
// *            |                 |
// *       RST -|     P1.3/UCA0TXD|----> PC 
// *            |                 |
// *            |                 |
// *            |     P1.2/UCA0RXD|<---- PC
// *            |                 |
// *
// *******************************************************************************/
/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

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

//打开微库 Options->Target->Code Generation->Use MicroLIB
//print函数调用fputc,通过串口发送到pc
int fputc(int ch, FILE *f)
{
	MAP_UART_transmitData(EUSCI_A0_BASE, ch & 0xFF);
	return ch;
}

/*
http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
*/

uint32_t  hh = 0,mm = 0,ss = 0;
uint32_t seth = 0,setm = 0,sets = 0;




//根据代码逻辑自行初始化
uint32_t start = 1,flag = 1;



const eUSCI_UART_Config uartConfig =
{
        EUSCI_A_UART_CLOCKSOURCE_SMCLK,          //选用SMCLK(1M)时钟源
        6,                                       // BRDIV = 6 ,clockPrescalar时钟分频系数 
        8,                                       // UCxBRF = 8  firstModReg (BRDIV、UCxBRF、 UCxBRS和SMCLK,用于设置串口波特率)
        17,                                      // UCxBRS = 17 secondModReg
        EUSCI_A_UART_NO_PARITY,                  // 校验位None
        EUSCI_A_UART_LSB_FIRST,                  // 低位优先,小端模式
        EUSCI_A_UART_ONE_STOP_BIT,               // 停止位1位
        EUSCI_A_UART_MODE,                       // UART mode
        EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // 设置为过采样,该数值为1
};

int main(void)
{  
    /* 停用开门狗 */
    MAP_WDT_A_holdTimer();
    
    //![Simple FPU Config]   
    MAP_FPU_enableModule();/*启用FPU加快DCO频率计算,注:DCO是内部数字控制振荡器,默认是3M频率*/    
    MAP_CS_setDCOFrequency(4000000);/* 设置DCO频率为指定频率,此处DCO=4M*/
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);/*设置MCLK(主时钟,可用于CPU主频等),MCLK=DCO频率/时钟分频系数,此处MCLK=DCO=4M*/
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);/*设置HSMCLK(子系统主时钟),HSMCLK=DCO频率/时钟分频系数,此处HSMCLK=DCO/4=1M*/
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);/*设置SMCLK(低速子系统主时钟,可用TimerA频率),SMCLK=DCO频率/时钟分频系数,此处SMCLK=DCO/4=1M*/    
    //![Simple FPU Config]
	
	/* 配置Timer32的第一个计数器为32位模式,周期模式,定时器频率=MCLK/定时器分频系数 此处第一个计数器频率=MCLK=4M */
    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_Timer32_setCount(TIMER32_0_BASE,4000000); /*设置Timer32第一个计数器计数周期,此处 20M/10M=2s*/ 
		MAP_Timer32_startTimer(TIMER32_0_BASE, false);/*Timer32第一个计数器以周期性模式开始计数*/
	
	
	
    /* 选用P1.2和P1.3使用UART模式 */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
    /* 使用uartConfig配置UART_A0 */
    MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);

    /* 使能UART_A0 */
    MAP_UART_enableModule(EUSCI_A0_BASE);
    
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); /*使能UART_A0串口接收中断*/ 
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0); /*使能UART_A0中断*/  
    MAP_Interrupt_enableMaster();  /*使能中断总开关*/      
    while(1){
			if(start == 1 && flag == 1){
				printf("%02d:%02d:%02d\r\n",hh,mm,ss);
				flag = 0;
			}
		}
}

/*UART_A0中断函数 */
//进阶使用
int fh = 0, fm = 0, fs = 0;
int change[6] = {0};
int to_change = 0;
void EUSCIA0_IRQHandler(void)
{
		
    char tmp = 0;
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); /*将UART_A0中断标志位的值赋值给status*/
    MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);/*清空UART_A0中断标志位*/
    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) /*判断是否为UART_A0接受中断*/
    {          
			tmp = MAP_UART_receiveData(EUSCI_A0_BASE);
			//添加代码逻辑,发送h8m3s2g:表示将时间设置为08:03:02,g表示设置完成开始计时
			switch(tmp)
			{
				case '1': case '2': case'3':
				case '4': case '5': case '6':
				case '7': case '8': case '9':case '0':
				
				to_change *= 10;
				to_change += (tmp - '0');
				if(fh){seth = to_change;}
				else if(fm){setm = to_change;}
				else if(fs){sets = to_change;}
				
				
				break;
				case 'h':
					fh = 1; fm = 0; fs = 0;
					to_change = 0;
				break;
				case 'm':
					fh = 0; fm = 1; fs = 0;
					to_change = 0;
				break;
				case 's':
					
					fh = 0; fm = 0;	fs = 1;
					to_change = 0;
				break;
				case 'g':
					fh = fm = fs = 0;
					hh = seth; mm = setm; ss = sets;
					seth = setm = sets = 0;
					to_change = 0;
				break;
				default:
					break;
			}
			
    }   
}


/* Timer32第一个计数器中断函数*/
//进行时钟计数处理(最低要求)
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE); /*清除Timer32第一个计数器中断标志*/  
	//添加代码
		MAP_Timer32_setCount(TIMER32_0_BASE, 4000000); 
		MAP_Timer32_startTimer(TIMER32_0_BASE, false);
	
		ss++;
			if(ss >= 60)
			{
				mm += ss / 60;
				ss %= 60;
			}
			if(mm >= 60)
			{
				hh += mm / 60;
				mm %= 60;
			}
			if(hh >= 24)
			{
				hh %= 24;
			}
			
		int temp = hh;
		int array[] = {'0', '0'};
		int cnt = 1;
		while(temp)
		{
			int a = temp % 10;
			temp /= 10;
			array[cnt--] = a + '0';
		}
		for(int i = 0; i < 2; i++)
		{
			MAP_UART_transmitData(EUSCI_A0_BASE, array[i] & 0xFF);
		}
		MAP_UART_transmitData(EUSCI_A0_BASE, ':' & 0xFF);
		
		temp = mm;
		array[0] = array[1] = '0';
		cnt = 1;
		while(temp)
		{
			int a = temp % 10;
			temp /= 10;
			array[cnt--] = a + '0';
		}
		for(int i = 0; i < 2; i++)
		{
			MAP_UART_transmitData(EUSCI_A0_BASE, array[i] & 0xFF);
		}
		MAP_UART_transmitData(EUSCI_A0_BASE, ':' & 0xFF);
		
		temp = ss;
		array[0] = array[1] = '0';
		cnt = 1;
		while(temp)
		{
			int a = temp % 10;
			temp /= 10;
			array[cnt--] = a + '0';
		}
		for(int i = 0; i < 2; i++)
		{
			MAP_UART_transmitData(EUSCI_A0_BASE, array[i] & 0xFF);
		}
		MAP_UART_transmitData(EUSCI_A0_BASE, '\n' & 0xFF);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值