- #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
- #include <time.h>
- #include <stdlib.h>
- #define MCLK_FREQUENCY 3000000
- #define PWM_PERIOD (MCLK_FREQUENCY/5000)
- unsigned int S1buttonDebounce = 0; // Deboounce state for button S1
- unsigned int S2buttonDebounce = 0; // Deboounce state for button S1
- int32_t interval = 0; // Elapsed interval between taps
- int32_t periods[4]; // LED blink periods for each color state
- int oldTick = 0; // SysTick value of previous tap
- int newTick = 0; // SysTick value of current tap
- int counting = 0; // Whether currently counting taps and interval between taps
- int count = 0; // Counts # of seconds elapsed since last tap
- int sysTickCount = 0; // Counts # of SysTick interrupts since last tap
- int taps = 0; // Counts # of taps from last reset
- /* Current color of the blinking RGB LED
- * 4 possible states: R, G, B, random color */
- unsigned int currentColor = 0;
- #define RED 255
- #define GREEN 255
- #define BLUE 255
- int bytesReceived = 7; // Keeps track of # UART bytes received
- int32_t receiveFreq = 0; // Receives LED blink frequency from GUI
- char start[5]; // Receives 'START' keyword
- int ack = 0; // Track acknowledgement sent to GUI
- /* TimerA UpMode Configuration Parameter */
- const Timer_A_UpModeConfig upConfig =
- {
- TIMER_A_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
- TIMER_A_CLOCKSOURCE_DIVIDER_1, // SMCLK/1 = 3MHz
- 45000, // 15ms debounce period
- TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer interrupt
- TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE , // Enable CCR0 interrupt
- TIMER_A_DO_CLEAR // Clear value
- };
- const Timer_A_UpModeConfig TA2upConfig =
- {
- TIMER_A_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
- TIMER_A_CLOCKSOURCE_DIVIDER_64, // SMCLK/64 ~ 46.9 kMHz
- 46875, // 1s timer period
- TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer interrupt
- TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE , // Enable CCR0 interrupt
- TIMER_A_DO_CLEAR // Clear value
- };
- /* Port mapper configuration register */
- const uint8_t port_mapping[] =
- {
- //Port P2:
- PM_TA0CCR1A, PM_TA0CCR2A, PM_TA0CCR3A, PM_NONE, PM_TA1CCR1A, PM_NONE, PM_NONE, PM_NONE
- };
- /* UART Configuration Parameter. These are the configuration parameters to
- * make the eUSCI A UART module to operate with a 115200 baud rate. These
- * values were calculated using the online calculator that TI provides
- * at:
- *http://processors.wiki.ti.com/index.php/USCI_UART_Baud_Rate_Gen_Mode_Selection
- */
- const eUSCI_UART_ConfigV1 uartConfig =
- {
- EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
- 26, // BRDIV = 26
- 0, // UCxBRF = 0
- 0, // UCxBRS = 0
- EUSCI_A_UART_NO_PARITY, // No Parity
- EUSCI_A_UART_LSB_FIRST, // MSB First
- EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
- EUSCI_A_UART_MODE, // UART mode
- EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION, // Low Frequency Mode
- EUSCI_A_UART_8_BIT_LEN // 8 bit data length
- };
- /*
- * Main function
- */
- int main(void)
- {
- /* Halting WDT and disabling master interrupts */
- MAP_WDT_A_holdTimer();
- MAP_Interrupt_disableMaster();
- /* Seed the pseudo random num generator */
- srand(TLV->RANDOM_NUM_1);
- /* Set the core voltage level to VCORE1 */
- MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
- /* Set 2 flash wait states for Flash bank 0 and 1*/
- MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
- MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
- /* Default SysTick period for all 4 color states = 0.5s */
- periods[0] = 1500000;
- periods[1] = 1500000;
- periods[2] = 1500000;
- periods[3] = 1500000;
- /* Initialize main clock to 3MHz */
- MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_3);
- MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
- MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
- MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
- /* Selecting P1.2 and P1.3 in UART mode and P1.0 as output (LED) */
- MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
- GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
- /* GPIO Setup for Pins 2.0-2.2 */
- MAP_PMAP_configurePorts((const uint8_t *) port_mapping, PMAP_P2MAP, 1,
- PMAP_DISABLE_RECONFIGURATION);
- MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,
- GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
- /* Confinguring P1.1 & P1.4 as an input and enabling interrupts */
- MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);
- MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);
- MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4, GPIO_HIGH_TO_LOW_TRANSITION);
- /* Configuring UART Module */
- MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
- /* Enable UART module */
- MAP_UART_enableModule(EUSCI_A0_BASE);
- /* Configure TimerA0 without Driverlib (CMSIS style register access) */
- TIMER_A0->CCR[0] = PWM_PERIOD;
- TIMER_A0->CCTL[1] = TIMER_A_CCTLN_OUTMOD_7; // CCR1 reset/set
- TIMER_A0->CCR[1] = PWM_PERIOD * (RED/255); // CCR1 PWM duty cycle
- TIMER_A0->CCTL[2] = TIMER_A_CCTLN_OUTMOD_7; // CCR2 reset/set
- TIMER_A0->CCR[2] = PWM_PERIOD * (0/255); // CCR2 PWM duty cycle
- TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_7; // CCR3 reset/set
- TIMER_A0->CCR[3] = PWM_PERIOD * (0/255); // CCR3 PWM duty cycle
- TIMER_A0->CTL = TIMER_A_CTL_SSEL__SMCLK | TIMER_A_CTL_MC__UP | TIMER_A_CTL_CLR; // SMCLK, up mode, clear TAR
- /* Configuring TimerA1 and TimerA2 for Up Mode using Driverlib*/
- MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);
- MAP_Timer_A_configureUpMode(TIMER_A2_BASE, &TA2upConfig);
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
- /* Configure and enable SysTick */
- MAP_SysTick_setPeriod(1500000);
- MAP_SysTick_enableModule();
- MAP_SysTick_enableInterrupt();
- /* Main while loop */
- while(1)
- {
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);
- MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
- MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
- MAP_Interrupt_enableInterrupt(INT_PORT1);
- MAP_Interrupt_enableInterrupt(INT_TA1_0);
- MAP_Interrupt_enableInterrupt(INT_TA2_0);
- MAP_Interrupt_enableMaster();
- MAP_PCM_gotoLPM0();
- }
- }
- /*
- * Port 1 interrupt handler. This handler is called whenever switches attached
- * to P1.1 (S1) and P1.4 (S2) are pressed.
- */
- void PORT1_IRQHandler(void)
- {
- newTick = MAP_SysTick_getValue();
- uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
- MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
- /* Handles S1 button press */
- if (status & GPIO_PIN1)
- {
- if (S1buttonDebounce == 0)
- {
- S1buttonDebounce = 1;
- MAP_Interrupt_disableInterrupt(INT_PORT1);
- MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0);
- MAP_Timer_A_stopTimer(TIMER_A2_BASE);
- MAP_Timer_A_configureUpMode(TIMER_A2_BASE, &TA2upConfig);
- MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_UP_MODE);
- count = 0;
- taps++;
- if (counting == 0)
- {
- oldTick = newTick;
- counting = 1;
- }
- else
- {
- if (sysTickCount == 0)
- {
- interval = oldTick - newTick;
- periods[currentColor] = interval/2;
- oldTick = newTick;
- }
- else
- {
- interval = (MAP_SysTick_getPeriod() - newTick) + ((sysTickCount-1) * MAP_SysTick_getPeriod()) + oldTick;
- oldTick = newTick;
- sysTickCount = 0;
- }
- periods[currentColor] = ((periods[currentColor] * (taps-2)) + interval/2) / (taps-1);
- MAP_SysTick_setPeriod(periods[currentColor]);
- }
- /* Start button debounce timer */
- MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE);
- }
- }
- /* Handles S2 button press */
- if (status & GPIO_PIN4)
- {
- if (S2buttonDebounce == 0)
- {
- S2buttonDebounce = 1;
- MAP_Interrupt_disableInterrupt(INT_PORT1);
- /* Cycle through R, G, B, random color */
- if (currentColor < 3)
- currentColor++;
- else
- currentColor = 0;
- switch(currentColor)
- {
- case 0: // Red
- TIMER_A0->CCR[1] = PWM_PERIOD * (RED/255); // CCR1 PWM duty cycle
- TIMER_A0->CCR[2] = PWM_PERIOD * (0/255); // CCR2 PWM duty cycle
- TIMER_A0->CCR[3] = PWM_PERIOD * (0/255); // CCR3 PWM duty cycle
- break;
- case 1: // Green
- TIMER_A0->CCR[1] = PWM_PERIOD * (0/255); // CCR1 PWM duty cycle
- TIMER_A0->CCR[2] = PWM_PERIOD * (GREEN/255); // CCR2 PWM duty cycle
- TIMER_A0->CCR[3] = PWM_PERIOD * (0/255); // CCR3 PWM duty cycle
- break;
- case 2: // Blue
- TIMER_A0->CCR[1] = PWM_PERIOD * (0/255); // CCR1 PWM duty cycle
- TIMER_A0->CCR[2] = PWM_PERIOD * (0/255); // CCR2 PWM duty cycle
- TIMER_A0->CCR[3] = PWM_PERIOD * (BLUE/255); // CCR3 PWM duty cycle
- break;
- case 3: // Random Color
- TIMER_A0->CCR[1] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR1 PWM duty cycle
- TIMER_A0->CCR[2] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR2 PWM duty cycle
- TIMER_A0->CCR[3] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR3 PWM duty cycle
- break;
- default:
- break;
- }
- /* Set current color's LED blink period */
- MAP_SysTick_setPeriod(periods[currentColor]);
- /* Start button debounce timer */
- MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE);
- }
- }
- }
- /*
- * Timer A1 interrupt handler. This handler determines whether to reset button
- * debounce after debounce timer expires.
- */
- void TA1_0_IRQHandler(void)
- {
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
- if (P1IN & GPIO_PIN1)
- {
- S1buttonDebounce = 0;
- }
- if (P1IN & GPIO_PIN4)
- {
- S2buttonDebounce = 0;
- }
- if ((P1IN & GPIO_PIN1) && (P1IN & GPIO_PIN4))
- {
- MAP_Timer_A_stopTimer(TIMER_A1_BASE);
- }
- MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,
- TIMER_A_CAPTURECOMPARE_REGISTER_0);
- }
- /*
- * Timer A2 interrupt handler. This handler resets tapping state variables if button S1 is
- * not pressed for more than 4 seconds.
- */
- void TA2_0_IRQHandler(void)
- {
- if (counting == 1)
- {
- if (count < 4)
- count++;
- else
- {
- counting = 0;
- count = 0;
- sysTickCount = 0;
- taps = 0;
- MAP_Timer_A_stopTimer(TIMER_A2_BASE);
- }
- }
- MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,
- TIMER_A_CAPTURECOMPARE_REGISTER_0);
- }
- /*
- * SysTick interrupt handler. This handler toggles RGB LED on/off.
- */
- void SysTick_Handler(void)
- {
- if (counting == 1)
- sysTickCount++;
- /* Toggle RGB LED OFF */
- if (TIMER_A0->CCTL[1] & TIMER_A_CCTLN_OUTMOD_7){
- TIMER_A0->CCTL[1] = TIMER_A_CCTLN_OUTMOD_0;
- TIMER_A0->CCTL[2] = TIMER_A_CCTLN_OUTMOD_0;
- TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_0;
- }
- /* Toggle RGB LED ON */
- else if (!(TIMER_A0->CCTL[1] & TIMER_A_CCTLN_OUTMOD_0)){
- if (currentColor == 3)
- {
- TIMER_A0->CCR[1] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR1 PWM duty cycle
- TIMER_A0->CCR[2] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR2 PWM duty cycle
- TIMER_A0->CCR[3] = (int)((rand() % 255) / 255.0f * PWM_PERIOD); // CCR3 PWM duty cycle
- }
- TIMER_A0->CCTL[1] = TIMER_A_CCTLN_OUTMOD_7;
- TIMER_A0->CCTL[2] = TIMER_A_CCTLN_OUTMOD_7;
- TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_7;
- }
- }
- /*
- * EUSCI A0 UART interrupt handler. Receives data from GUI and sets LED color/blink frequency
- */
- void EUSCIA0_IRQHandler(void)
- {
- int receiveByte = UCA0RXBUF;
- /* Send acknowledgement to the GUI */
- if (ack == 0) {
- MAP_UART_transmitData(EUSCI_A0_BASE, 'A');
- ack = 1;
- }
- /* Wait for 'START' keyword to be received before changing color */
- if (bytesReceived > 6) {
- start[0] = start[1];
- start[1] = start[2];
- start[2] = start[3];
- start[3] = start[4];
- start[4] = receiveByte;
- if (start[0] == 'S' && start[1] == 'T' && start[2] == 'A' && start[3] == 'R' && start[4] == 'T')
- bytesReceived = -1;
- }
- /* Receive/Set color and frequency of LED */
- else {
- if (bytesReceived == 0)
- TIMER_A0->CCR[1] = (int)(PWM_PERIOD * (receiveByte/255.0f)); // CCR3 PWM duty cycle
- else if (bytesReceived == 1)
- TIMER_A0->CCR[2] = (int)(PWM_PERIOD * (receiveByte/255.0f)); // CCR3 PWM duty cycle
- else if (bytesReceived == 2)
- TIMER_A0->CCR[3] = (int)(PWM_PERIOD * (receiveByte/255.0f)); // CCR3 PWM duty cycle
- else if (bytesReceived == 3)
- {
- receiveFreq = 0;
- receiveFreq |= receiveByte;
- }
- else if (bytesReceived == 4)
- receiveFreq |= (receiveByte << 8);
- else if (bytesReceived == 5)
- receiveFreq |= (receiveByte << 16);
- else if (bytesReceived == 6)
- {
- receiveFreq |= (receiveByte << 24);
- MAP_SysTick_setPeriod(receiveFreq);
- ack = 0;
- }
- }
- if (bytesReceived < 7)
- bytesReceived++;
- }
由此可见,基本上都是采用按键中断的形式来触发改变LED点亮的状态。接下来需要将编译好的二进制文件烧写到开发板中,我这里采用的是JLink调试下载器,使用DAP方式也是可以下载,但速度有点慢,因此不推荐。将JLink调试下载器与开发板的下载接口相连接,打开Keil中的魔法棒,在Debug选项中勾选JLink方式,能够识别到JLink设备说明安装的JLink驱动也没问题了。
然后在Keil的菜单栏中直接点击load图标,即可完成程序的烧写。
然后将板卡重新上电,与原来出厂的程序一样,也是通过按键S1来切换灯光变化的频率,通过按键S2来切换灯光的颜色变化。具体的操作演示视频如下:
https://v.youku.com/v_show/id_XNDYzNjg3NDg5Mg==.html
https://v.youku.com/v_show/id_XNDYzNTQxNDEyOA==.html
接下来体验一下使用TI主推的CCS集成开发工具,通过TI的官网很容易获得CCS的下载地址,工具完全免费,选择最新版的下载安装。下载的网址如下截图:
解压“CCS10.0.0.00010_win64.zip”文件,双击“ccs_setup_10.0.0.00010.exe”,然后进入安装界面:
一路默认,今日选择组件界面,我们使用的是MSP-EXP432P401R 版本1.0(黑色)LaunchPad 开发套件,因此勾选如下图所示即可
根据需求,勾选是否需要安装调试JLink驱动,安装过程中建议将杀毒软件关闭,此次将CCS安装在C盘,安装进度信息如下:
安装完成后重启计算机,打开安装好的CCS软件,初次使用建议先更新Code Composer Studio IDE,然后创建基本的SimpleLink MSP432项目,与其它的软件设置一样,选择器件型号,设置项目名称,获取模板工程示例选择从“TI资源浏览器导入SimpleLink”示例,然后进行调试器的设置,调试应用程序。具体操作可参照《zhcu166f.pdf》文档,附件奉上:
以上就是基于MSP-EXP432P401R开发板的开发demo体验,总体感觉TI的资源整理的很规范,文档资料相当齐全。TI的SimpleLink MCU SDK兼容性比较好,SimpleLink MCU SDK包括支持CC13xx/CC26xx、CC32xx 和MSP432器件的整体框架,此三个MCU系列均可使用相同的顶层API。