这几天尝试玩了一下MSP432P401R的ADC采样外设。MSP432P401R这款单片机的ADC是14位精度,通过软件过采样可以支持达到16位精度,高达1Msps采样速率。有单端和差分方式输入,2个窗口比较器,有32个采样通道,其中内部通道6个。有3个内部电压基准:1.2V,1.45V,2.5V。
下图是ADC框图:
正好自己有用模拟型加速度传感器MMA7361,以前项目做震动和倾斜检测用的。这次正好拿来测试一下MSP432P401R的ADC功能。MMA7361有XYZ轴模拟电压,需要3路AD采样。
硬件连接:
Z轴—>P5.5(A0)
Y轴—>P5.4(A1)
X轴—>P4.7(A6)
选择这3个引脚是因为板子上3个引脚正好在一起,方便连接。
配置ADC为3个通道连续循环转换,使用软件触发采样源,基准电压使用AVCC=3.3V。程序实现简单的倾斜和震动检测,当发生倾斜或者震动时点亮LED灯。可以调整感应灵敏度阈值。
//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // main.c - MSP-EXP432P401R Out Of Box Demo // //Blinks RGB LED at 1Hz. Button S1 allows taps-to-beat that will //match the RGB blink frequency to the tap frequency. Button S2 //cycles through 4 different color states, R/G/B/RandomColor, each //with its saved blink frequency. // //The demo also accepts UART data from the Out Of Box GUI that //allows changing the RGB LED's color with a color wheel and //frequency by entering desired beats-per-minute // //**************************************************************************** #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <time.h> #include <stdlib.h> #define MCLK_FREQUENCY 3000000 int sysTickCount = 0;// Counts # of SysTick interrupts since last tap /* 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: *processors.wiki.ti.com/.../USCI_UART_Baud_Rate_Gen_Mode_Selection */ const eUSCI_UART_Config uartConfig = {EUSCI_A_UART_CLOCKSOURCE_SMCLK,// SMCLK Clock Source26,// BRDIV = 260,// UCxBRF = 00,// UCxBRS = 0EUSCI_A_UART_NO_PARITY,// No ParityEUSCI_A_UART_LSB_FIRST,// MSB FirstEUSCI_A_UART_ONE_STOP_BIT,// One stop bitEUSCI_A_UART_MODE,// UART modeEUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION // Low Frequency Mode }; /* Statics */ static volatile uint16_t curADCResult; static volatile float normalizedADCRes; uint8_t AdcValue[16]; uint32_t tickcnt; uint16_t ADC_x[5]; uint16_t ADC_y[5]; uint16_t ADC_z[5]; uint16_t ADC_x_cnt = 0; uint16_t ADC_y_cnt = 0; uint16_t ADC_z_cnt = 0; uint16_t ADC_x_cen = 0; //ˮƽֵ uint16_t ADC_y_cen = 0; //ˮƽֵ uint16_t ADC_z_cen = 0; //ˮƽֵ uint16_t ADC_x_cur = 0; //µ±Ç°Öµ uint16_t ADC_y_cur = 0; //µ±Ç°Öµ uint16_t ADC_z_cur = 0; //µ±Ç°Öµ uint16_t SortValue(uint16_t *buf, uint16_t len) { uint16_t i,j; uint16_t temp; if(len < 3) return 0; for(i=1; i<len; i++) { for(j = 0; j < (len-i); j++) { if(buf[j] > buf[j+1]) { temp = buf[j]; buf[j] = buf[j+1]; buf[j+1] = temp; } } } temp = 0; for(i=1;i<(len-1);i++) { temp += buf[i]; } temp /= (len-2); return temp; } /* * Main function */ int main(void) {/* Halting WDT and disabling master interrupts */MAP_WDT_A_holdTimer();MAP_Interrupt_disableMaster();/* Initializing Variables */curADCResult = 0; AdcValue[0] = 0xff; AdcValue[1] = 0xff; AdcValue[2] = 0; AdcValue[3] = 0; AdcValue[4] = 0; AdcValue[5] = 0; AdcValue[6] = 0; AdcValue[7] = 0; AdcValue[8] = 0; AdcValue[9] = 0;/* 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);/* 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 );/* 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);/* Selecting P1.2 and P1.3 in UART mode */MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);/* Configuring UART Module */MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);/* Enable UART module */MAP_UART_enableModule(EUSCI_A0_BASE); //P1.0,P2.0,P2.1,P2.2MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);/* Enabling the FPU for floating point operation */MAP_FPU_enableModule();MAP_FPU_enableLazyStacking();//![Single Sample Mode Configure]/* Initializing ADC (MCLK/1/1) */MAP_ADC14_enableModule();MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_4,0);/* Configuring GPIOs (5.5 A0)(5.4 A1) */MAP_GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P5, GPIO_PIN4|GPIO_PIN5, GPIO_TERTIARY_MODULE_FUNCTION); //(4.7 A6) MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION);/* Configuring ADC Memory */MAP_ADC14_configureMultiSequenceMode(ADC_MEM0,ADC_MEM2, true);MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A0, false);MAP_ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A1, false); MAP_ADC14_configureConversionMemory(ADC_MEM2, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A6, false);/* Configuring Sample Timer */MAP_ADC14_enableSampleTimer(ADC_MANUAL_ITERATION);/* Enabling/Toggling Conversion */MAP_ADC14_enableConversion();//![Single Sample Mode Configure]/* Configure and enable SysTick 1ms*/MAP_SysTick_setPeriod(1500);MAP_SysTick_enableModule();MAP_SysTick_enableInterrupt(); /* Enabling interrupts */MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);MAP_ADC14_enableInterrupt(ADC_INT0 | ADC_INT1 | ADC_INT2);MAP_Interrupt_enableInterrupt(INT_EUSCIA0);MAP_Interrupt_enableInterrupt(INT_PORT1);MAP_Interrupt_enableInterrupt(INT_ADC14);MAP_Interrupt_enableMaster();/* Main while loop */MAP_ADC14_toggleConversionTrigger(); tickcnt = sysTickCount;while(1){ if((sysTickCount - tickcnt) > 10) { MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[0]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[1]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[2]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[3]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[4]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[5]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[6]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[7]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[8]); MAP_UART_transmitData(EUSCI_A0_BASE, AdcValue[9]); if((ADC_x_cur > (ADC_x_cen + 0x800)) || ((ADC_x_cur + 0x800) < (ADC_x_cen))) { MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0); }else { MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0); } if((ADC_y_cur > (ADC_y_cen + 0x800)) || ((ADC_y_cur + 0x800) < (ADC_y_cen))) { MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1); }else { MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1); } if((ADC_z_cur > (ADC_z_cen + 0x800)) || ((ADC_z_cur + 0x800) < (ADC_z_cen))) { MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN2); }else { MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2); } MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); tickcnt = sysTickCount; } //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){ MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0); ADC_x_cen = ((AdcValue[6]<<8) | (AdcValue[7])); ADC_y_cen = ((AdcValue[4]<<8) | (AdcValue[5])); ADC_z_cen = ((AdcValue[2]<<8) | (AdcValue[3]));}/* Handles S2 button press */if (status & GPIO_PIN4){} }//![Single Sample Result] /* ADC Interrupt Handler. This handler is called whenever there is a conversion * that is finished for ADC_MEM0. */ void ADC14_IRQHandler(void) {uint64_t status = MAP_ADC14_getEnabledInterruptStatus();MAP_ADC14_clearInterruptFlag(status);if (ADC_INT0 & status){curADCResult = MAP_ADC14_getResult(ADC_MEM0);normalizedADCRes = (curADCResult * 3.3) / 16384; ADC_z[ADC_z_cnt++] = curADCResult; if(ADC_z_cnt == 5) { ADC_z_cnt = 0; ADC_z_cur = SortValue(ADC_z, 5); AdcValue[2] = ADC_z_cur>>8; AdcValue[3] = ADC_z_cur&0xff; }MAP_ADC14_toggleConversionTrigger();}if (ADC_INT1 & status){curADCResult = MAP_ADC14_getResult(ADC_MEM1);normalizedADCRes = (curADCResult * 3.3) / 16384; ADC_y[ADC_y_cnt++] = curADCResult; if(ADC_y_cnt == 5) { ADC_y_cnt = 0; ADC_y_cur = SortValue(ADC_y, 5); AdcValue[4] = ADC_y_cur>>8; AdcValue[5] = ADC_y_cur&0xff; }MAP_ADC14_toggleConversionTrigger();}if (ADC_INT2 & status){curADCResult = MAP_ADC14_getResult(ADC_MEM2);normalizedADCRes = (curADCResult * 3.3) / 16384; ADC_x[ADC_x_cnt++] = curADCResult; if(ADC_x_cnt == 5) { ADC_x_cnt = 0; ADC_x_cur = SortValue(ADC_x, 5); AdcValue[6] = ADC_x_cur>>8; AdcValue[7] = ADC_x_cur&0xff; }MAP_ADC14_toggleConversionTrigger();} } /* * SysTick interrupt handler. This handler toggles RGB LED on/off. */ void SysTick_Handler(void) { sysTickCount++; } /* * 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 */MAP_UART_transmitData(EUSCI_A0_BASE, 'A'); MAP_UART_transmitData(EUSCI_A0_BASE, receiveByte); }
gaoyang9992006:
楼主的模块装备挺丰富的。
Susan Yang:
谢谢分享!
user5284236:
对MSP432的ADC做了很详细的介绍,通过对MMA7361的实际采样验证,贴出代码,讲解了硬件接线,很好的展示了ADC的功能。
程序也有结果展示,不错的评测。
user5845663:
很棒的介绍,还有示例程序,便于他人学习和验证。
user1913794:
楼主硬件有3路AD采样,同时果断的开源了代码,值得学习。同时对MSP432的ADC做了很详细的介绍,通过对MMA7361的实际采样验证,讲解了硬件接线,很好的展示了ADC的功能。
user5788289:
谢谢大家支持。
user5788289:
本来还计划准备加入OLED显示数据,和加速度传感器配合实现oled根据加速度值旋转屏幕,类是手机屏幕旋转功能的。由于时间关系,加上本身比较忙,就没完成该项功能。上面暂时就实现了倾斜XYZ方向点亮LED灯。后续有时间再深入测试一番,做点实际应用。
user3687004:
(1)项目开发不错,有过程有试验。
(2)ADC运用熟练,14位精度没有体现。
(3)两个方向的倾斜用不同颜色的灯指示,创意十足,就是测量精度堪忧。
(4)调整感应灵敏度阈值,没有体现。
user3735680:
这篇分享讲解的是ADC采样和加速度传感器的使用,通过对板卡的ADC文字描述和框图图片给出了ADC的一些参数,同时对加速度传感器简要介绍,接着给出了程序源码,并附上了实物图片,总的来说,具有比较好的参考价值!
ping yang:
1.楼主开源的做法值得肯定加赞赏。
2.评测不同方向加速度创意很好。
3.如果在倾斜角度上体现灵敏度阈值调节效果,相信大家会有更好的收获。感谢楼主的辛苦付出。