本帖最后由 Litthins 于 2018-6-13 00:21 编辑
LPC双核挑战赛 项目提交
首先非常感谢论坛能给我们这么好的机会了解lpc54114这块优秀的板子。
视频链接:LPC双核挑战赛 Litthins团队作品 欢迎大家来看!
——————————————我是分界线——————————————
一种基于电磁无损检测方法的 管状零件现场缺陷定性检测仪
设 计 报 告 书
作者:邓承杰、尚亚期、鄢贵祥、李小高 时间:2018年6月10日
一.摘要 管道在工业系统中有着十分关键的作用,很多工程现场都对管道质量有严格的要求。对于新生产的管状零件而言,铸件内部容易出现不可控的气泡或疏松缺陷,导致产品品质下降甚至出现废件,而在运行的管道时常需要检修,比如危险裂纹的检查,这时就需要用到无损检测技术,也就是在不损坏零件的前提下完成检验操作。在无损检测中,漏磁检测对管状零件横向和纵向裂纹的检验有很大的优势。本项目意在开发一种基于NXP LPC54114的电磁无损缺陷定性检测仪,力求可以在生产现场直接使用。其中步进电机的控制由M0+核实现,其他功能由M4核实现,包括ADC、USART等。并可配合PC软件(包含在附件中)实现3D立体可视化操作。
二.结构设计 为实现设计所要求的运动,设计了本传动机构,并通过3D打印技术打印了模型。但由于成本问题,机构设计存在着一些不足之处,这个成本之内,也算是比较优良的设计。现对其进行以下介绍,主要介绍其要实现的功能与作用。 底座:该结构用来固定四个电机,中间部分需要设计两个齿轮来实现电机转动位置的转移。 主动轮:用来传递运动。底盘:该结构用来限制从动轮的自由度,使其实现平稳转动。 凹圆槽:支撑转台以及转台上的零件。 螺线管:用于缠绕线圈,并可安装在三个凸台之上,而凸台则由于丝杠的旋转而实现上下移动,从而使线圈能够上下移动。右图结构为中间旋转部分,用来实现被检测工件的旋转,工件放在转台上即可实现旋转运动。该机构使传感器的上下运动(通过四周三个步进电机实现)和零件的旋转运动(通过中间步进电机齿轮传动实现)成为可能,是扫描功能实现的基础。
三.检测原理 无损检测原理:通有交流电的螺线管可在内部产生交变磁场,交变磁场可使置于螺线管内的导体表面产生周向涡电流,其原理如图所示。
将被检测金属放入转台上,螺线管内的线圈通入交流电,根据电磁原理,有缺陷的金属导体会在缺陷处产生畸变磁场。安装在螺线管上的传感器将检测到的畸变信号传到电脑,然后经过处理进行显示。转台转动实现被检测金属周向检测,三个电机带动丝杠转动,支撑螺旋管向上运动,实现轴向检测。因此,本检测装置可以实现周向和轴向全方位检测。
四.LPC54114部分本作品使用IAR软件环境开发,所用sdk为NXP MCUXpresso SDK Builder创建。参考sdk中双核的demo,将四路步进电机的控制交由小核M0+实现,大核M4主要实现ADC0_3通道的电压信号采集,并将电压信号通过USART发送到PC端。具体使用到板上GPIO资源,ADC资源和USART资源。 具体系统运行流程图和硬件电路图如上图所示。开机上电后,初始化片上资源。主核在完成ADC和USART配置后,转到小核初始化片上GPIO,产生步进电机控制信号。同时,大核开始从ADC上读取霍尔元件的电压值,并经由USART发送给PC机。AD转换过程由预置信号采集数量确定,当采集到足够多的数据,则大核进入deepsleep/powerdown模式,可使小核停止产生步进电机控制信号,系统等待下次初始化,进行第二次信号采集。 部分pin_mux.c文件(大核): - void BOARD_InitPins_Core0(void) { /* Function assigned for the Cortex-M4F */
- CLOCK_EnableClock(kCLOCK_Iocon); /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */
- const uint32_t port0_pin0_config = (
- IOCON_PIO_FUNC1 | /* Pin is configured as FC0_RXD_SDA_MOSI */
- IOCON_PIO_MODE_INACT | /* No addition pin function */
- IOCON_PIO_INV_DI | /* Input function is not inverted */
- IOCON_PIO_DIGITAL_EN | /* Enables digital function */
- IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
- IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
- IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
- );
- IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN0_IDX, port0_pin0_config); /* PORT0 PIN0 (coords: 31) is configured as FC0_RXD_SDA_MOSI */
- const uint32_t port0_pin1_config = (
- IOCON_PIO_FUNC1 | /* Pin is configured as FC0_TXD_SCL_MISO */
- IOCON_PIO_MODE_INACT | /* No addition pin function */
- IOCON_PIO_INV_DI | /* Input function is not inverted */
- IOCON_PIO_DIGITAL_EN | /* Enables digital function */
- IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
- IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
- IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
- );
- IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN1_IDX, port0_pin1_config); /* PORT0 PIN1 (coords: 32) is configured as FC0_TXD_SCL_MISO */
- }
- void BOARD_InitADCUSARTPins(void)
- {
- /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */
- CLOCK_EnableClock(kCLOCK_Iocon);
-
- const uint32_t port1_pin0_config = (/* Pin is configured as ADC0_3 */
- IOCON_PIO_FUNC0 |
- /* No addition pin function */
- IOCON_PIO_MODE_INACT
- /* Input function is not inverted */
- /*IOCON_PIO_INV_DI*/);
- /* PORT1 PIN0 (coords: 32) is configured as ADC0_3 */
- IOCON_PinMuxSet(IOCON, 1U, 0U, port1_pin0_config);
-
- /* USART5 RX/TX pin */
- IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN20_IDX, IOCON_MODE_INACT | IOCON_FUNC1 | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//RX
- IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN18_IDX, IOCON_MODE_INACT | IOCON_FUNC1 | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//TX
- }
复制代码 部分小核主程序:
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- #define LED_INIT1() GPIO_PinInit(GPIO, BOARD_8_GPIO_PORT, BOARD_8_GPIO_PIN, &led_config);
- #define LED_HIGH1() GPIO_PinWrite(GPIO, BOARD_8_GPIO_PORT, BOARD_8_GPIO_PIN, 1);
- #define LED_LOW1() GPIO_PinWrite(GPIO, BOARD_8_GPIO_PORT, BOARD_8_GPIO_PIN, 0);
- #define LED_INIT2() GPIO_PinInit(GPIO, BOARD_9_GPIO_PORT, BOARD_9_GPIO_PIN, &led_config);
- #define LED_HIGH2() GPIO_PinWrite(GPIO, BOARD_9_GPIO_PORT, BOARD_9_GPIO_PIN, 1);
- #define LED_LOW2() GPIO_PinWrite(GPIO, BOARD_9_GPIO_PORT, BOARD_9_GPIO_PIN, 0);
- #define LED_INIT3() GPIO_PinInit(GPIO, BOARD_10_GPIO_PORT, BOARD_10_GPIO_PIN, &led_config);
- #define LED_HIGH3() GPIO_PinWrite(GPIO, BOARD_10_GPIO_PORT, BOARD_10_GPIO_PIN, 1);
- #define LED_LOW3() GPIO_PinWrite(GPIO, BOARD_10_GPIO_PORT, BOARD_10_GPIO_PIN, 0);
- #define LED_INIT4() GPIO_PinInit(GPIO, BOARD_11_GPIO_PORT, BOARD_11_GPIO_PIN, &led_config);
- #define LED_HIGH4() GPIO_PinWrite(GPIO, BOARD_11_GPIO_PORT, BOARD_11_GPIO_PIN, 1);
- #define LED_LOW4() GPIO_PinWrite(GPIO, BOARD_11_GPIO_PORT, BOARD_11_GPIO_PIN, 0);
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*!
- * @brief Function to create delay for Led blink.
- */
- void delay(void)
- {
- volatile uint32_t i = 0;
- for (i = 0; i < 15000; ++i)
- {
- __asm("NOP"); /* delay */
- }
- }
- /*!
- * @brief Application-specific implementation of the SystemInitHook() weak function.
- */
- void SystemInitHook(void)
- {
- /* Initialize MCMGR - low level multicore management library. Call this
- function as close to the reset entry as possible to allow CoreUp event
- triggering. The SystemInitHook() weak function overloading is used in this
- application. */
- MCMGR_EarlyInit();
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- uint32_t startupData, i;
- mcmgr_status_t status;
- /* Define the init structure for the output LED pin*/
- gpio_pin_config_t led_config = {
- kGPIO_DigitalOutput, 0,
- };
- /* Initialize MCMGR, install generic event handlers */
- MCMGR_Init();
- /* Get the startup data */
- do
- {
- status = MCMGR_GetStartupData(&startupData);
- } while (status != kStatus_MCMGR_Success);
- /* Make a noticable delay after the reset */
- /* Use startup parameter from the master core... */
- for (i = 0; i < startupData; i++)
- delay();
- /* Init board hardware.*/
- /* enable clock for GPIO */
- CLOCK_EnableClock(kCLOCK_Gpio0);
- CLOCK_EnableClock(kCLOCK_Gpio1);
- BOARD_InitPins_Core1();
- /* Configure LED */
- LED_INIT1();
- LED_INIT2();
- LED_INIT3();
- LED_INIT4();
-
- while (1)
- {
- LED_LOW4();
- LED_HIGH1();
- delay();
- LED_LOW1();
- LED_HIGH2();
- delay();
- LED_LOW2();
- LED_HIGH3();
- delay();
- LED_LOW3();
- LED_HIGH4();
- delay();
- }
- }
复制代码 部分大核主程序:
- #include "fsl_debug_console.h"
- #include "fsl_gpio.h"
- #include "board.h"
- #include "mcmgr.h"
- #include "fsl_usart.h"
- #include <stdbool.h>
- #include "fsl_common.h"
- #include "pin_mux.h"
- #include "fsl_device_registers.h"
- #include "fsl_adc.h"
- #include "fsl_clock.h"
- #include "fsl_power.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- #define DEMO_USART USART5
- #define DEMO_USART_CLK_SRC kCLOCK_Flexcomm5
- #define DEMO_USART_CLK_FREQ CLOCK_GetFreq(kCLOCK_Flexcomm5)
- #define DEMO_ADC_BASE ADC0
- #define DEMO_ADC_SAMPLE_CHANNEL_NUMBER 3U
- /* Address of RAM, where the image for core1 should be copied */
- #define CORE1_BOOT_ADDRESS (void *)0x20010000
- #if defined(__CC_ARM)
- extern uint32_t Image$CORE1_REGION$Base;
- extern uint32_t Image$CORE1_REGION$Length;
- #define CORE1_IMAGE_START &Image$CORE1_REGION$Base
- #elif defined(__ICCARM__)
- extern unsigned char core1_image_start[];
- #define CORE1_IMAGE_START core1_image_start
- #elif defined(__GNUC__)
- extern const char m0_image_start[];
- extern const char *m0_image_end;
- extern int m0_image_size;
- #define CORE1_IMAGE_START ((void *)m0_image_start)
- #define CORE1_IMAGE_SIZE ((void *)m0_image_size)
- #endif
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /* USART user callback */
- void USART_UserCallback(USART_Type *base, usart_handle_t *handle, status_t status, void *userData);
- static void ADC_Configuration(void);
- #ifdef CORE1_IMAGE_COPY_TO_RAM
- uint32_t get_core1_image_size(void);
- #endif
- void delay(void)
- {
- volatile uint32_t i = 0;
- for (i = 0; i < 80000; ++i)
- {
- __asm("NOP"); /* delay */
- }
- }
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- usart_handle_t g_uartHandle;
- volatile bool rxBufferEmpty = true;
- volatile bool txBufferFull = false;
- volatile bool txOnGoing = false;
- volatile bool rxOnGoing = false;
- adc_result_info_t adcResultInfoStruct;
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /* USART user callback */
- void USART_UserCallback(USART_Type *base, usart_handle_t *handle, status_t status, void *userData)
- {
- userData = userData;
- if (kStatus_USART_TxIdle == status)
- {
- txBufferFull = false;
- txOnGoing = false;
- }
- if (kStatus_USART_RxIdle == status)
- {
- rxBufferEmpty = false;
- rxOnGoing = false;
- }
- }
- static void ADC_ClockPower_Configuration(void)
- {
- /* SYSCON power. */
- POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
- POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); /* Power on the analog power supply. */
- //POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); /* Power on the reference voltage source. */
- //POWER_DisablePD(kPDRUNCFG_PD_TEMPS); /* Power on the temperature sensor. */
- /* Enable the clock. */
- CLOCK_AttachClk(kFRO12M_to_MAIN_CLK);
- /* CLOCK_AttachClk(kMAIN_CLK_to_ADC_CLK); */
- /* Sync clock source is not used. Using sync clock source and would be divided by 2.
- * The divider would be set when configuring the converter.
- */
- CLOCK_EnableClock(kCLOCK_Adc0); /* SYSCON->AHBCLKCTRL[0] |= SYSCON_AHBCLKCTRL_ADC0_MASK; */
- }
- #ifdef CORE1_IMAGE_COPY_TO_RAM
- uint32_t get_core1_image_size()
- {
- uint32_t core1_image_size;
- #if defined(__CC_ARM)
- core1_image_size = (uint32_t)&Image$CORE1_REGION$Length;
- #elif defined(__ICCARM__)
- #pragma section = "__sec_core"
- core1_image_size = (uint32_t)__section_end("__sec_core") - (uint32_t)&core1_image_start;
- #elif defined(__GNUC__)
- core1_image_size = (uint32_t)m0_image_size;
- #endif
- return core1_image_size;
- }
- #endif
- /*!
- * @brief Application-specific implementation of the SystemInitHook() weak function.
- */
- void SystemInitHook(void)
- {
- /* Initialize MCMGR - low level multicore management library. Call this
- function as close to the reset entry as possible to allow CoreUp event
- triggering. The SystemInitHook() weak function overloading is used in this
- application. */
- MCMGR_EarlyInit();
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- usart_config_t config;
- usart_transfer_t xfer;
- /* Initialize MCMGR, install generic event handlers */
- MCMGR_Init();
- /* Init board hardware.*/
- /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
- CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
- CLOCK_AttachClk(kFRO12M_to_FLEXCOMM5);
- RESET_PeripheralReset(kFC5_RST_SHIFT_RSTn);
-
- BOARD_InitPins_Core0();
- BOARD_InitADCUSARTPins();
- BOARD_BootClockFROHF48M();
- BOARD_InitDebugConsole();
-
- PRINTF("\r\nThis is Primary Core!\r\n\n");
-
- USART_GetDefaultConfig(&config);
- config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
- config.enableTx = true;
- config.enableRx = true;
- PRINTF("USART Configured!\r\n");
- USART_Init(DEMO_USART, &config, DEMO_USART_CLK_FREQ);
- USART_TransferCreateHandle(DEMO_USART, &g_uartHandle, USART_UserCallback, NULL);
- ADC_ClockPower_Configuration();
- PRINTF("ADC Basic Function Configure!\r\n");
- #if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
- #if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
- /* Calibration after power up. */
- if (ADC_DoSelfCalibration(DEMO_ADC_BASE))
- #else
- uint32_t frequency;
- #if defined(SYSCON_ADCCLKDIV_DIV_MASK)
- frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) / CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
- #else
- frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
- #endif /* SYSCON_ADCCLKDIV_DIV_MASK */
- /* Calibration after power up. */
- if (ADC_DoSelfCalibration(DEMO_ADC_BASE, frequency))
- #endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */
- {
- PRINTF("ADC_DoSelfCalibration() Done.\r\n");
- }
- else
- {
- PRINTF("ADC_DoSelfCalibration() Failed.\r\n");
- }
- #endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */
- /* Configure the converter and work mode. */
- ADC_Configuration();
- PRINTF("ADC Configured!\r\n");
- #ifdef CORE1_IMAGE_COPY_TO_RAM
- /* Calculate size of the image - not required on MCUXpresso IDE. MCUXpresso copies the secondary core
- image to the target memory during startup automatically */
- uint32_t core1_image_size;
- core1_image_size = get_core1_image_size();
- PRINTF("Copy Secondary core image to address: 0x%x, size: %d\n", CORE1_BOOT_ADDRESS, core1_image_size);
- /* Copy Secondary core application from FLASH to the target memory. */
- memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size);
- #endif
- /* Boot Secondary core application */
- PRINTF("Starting Secondary core.\r\n");
- MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, 5, kMCMGR_Start_Synchronous);
- PRINTF("This is secondary Core!\r\n");
-
- uint32_t count=0;
- for(uint8_t i=0;i<10;i++)
- delay();
- while (1)
- {
- PRINTF("ADC Count = %d\r\n", count);
- delay();
- if(count>200)
- break;
- count=count+1;
- /* Get the input from terminal and trigger the converter by software. */
- void delay();
- ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
- /* Wait for the converter to be done. */
- while (!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER, &adcResultInfoStruct))
- {
- }
- PRINTF("adcResultInfoStruct.result = %d\r\n", adcResultInfoStruct.result);
- PRINTF("\r\n");
-
- uint8_t ADCMSG[5];
- ADCMSG[4]='\0';
- ADCMSG[3]=adcResultInfoStruct.result%10+48;
- ADCMSG[2]=adcResultInfoStruct.result/10%10+48;
- ADCMSG[1]=adcResultInfoStruct.result/10/10%10+48;
- ADCMSG[0]=adcResultInfoStruct.result/10/10/10%10+48;
- xfer.data = ADCMSG;
- xfer.dataSize = sizeof(ADCMSG)-1;
- txOnGoing = true;
- USART_TransferSendNonBlocking(DEMO_USART, &g_uartHandle, &xfer);
- }
- uint8_t ADCMSG[5];
- ADCMSG[4]='\0';
- ADCMSG[3]=88;
- ADCMSG[2]=88;
- ADCMSG[1]=88;
- ADCMSG[0]=88;
- xfer.data = ADCMSG;
- xfer.dataSize = sizeof(ADCMSG)-1;
- txOnGoing = true;
- USART_TransferSendNonBlocking(DEMO_USART, &g_uartHandle, &xfer);
- PRINTF("Electromagnetic Nondestructive Testing Completed!\r\n");
- PRINTF("\r\n");
-
- POWER_EnterDeepPowerDown(0U);
- }
- static void ADC_Configuration(void)
- {
- adc_config_t adcConfigStruct;
- adc_conv_seq_config_t adcConvSeqConfigStruct;
- /* Configure the converter. */
- #if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE
- adcConfigStruct.clockMode = kADC_ClockSynchronousMode; /* Using sync clock source. */
- #endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE */
- adcConfigStruct.clockDividerNumber = 1; /* The divider for sync clock is 2. */
- #if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
- adcConfigStruct.resolution = kADC_Resolution12bit;
- #endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
- #if defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) & FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL
- adcConfigStruct.enableBypassCalibration = false;
- #endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL */
- #if defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) & FSL_FEATURE_ADC_HAS_CTRL_TSAMP
- adcConfigStruct.sampleTimeNumber = 0U;
- #endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP */
- #if defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) & FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE
- adcConfigStruct.enableLowPowerMode = false;
- #endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE */
- #if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG
- adcConfigStruct.voltageRange = kADC_HighVoltageRange;
- #endif /* FSL_FEATURE_ADC_HAS_TRIM_REG */
- ADC_Init(DEMO_ADC_BASE, &adcConfigStruct);
- #if !(defined(FSL_FEATURE_ADC_HAS_NO_INSEL) && FSL_FEATURE_ADC_HAS_NO_INSEL)
- /* Use the temperature sensor input to channel 0. */
- ADC_EnableTemperatureSensor(DEMO_ADC_BASE, true);
- #endif /* FSL_FEATURE_ADC_HAS_NO_INSEL. */
- /* Enable channel DEMO_ADC_SAMPLE_CHANNEL_NUMBER's conversion in Sequence A. */
- adcConvSeqConfigStruct.channelMask =
- (1U << DEMO_ADC_SAMPLE_CHANNEL_NUMBER); /* Includes channel DEMO_ADC_SAMPLE_CHANNEL_NUMBER. */
- adcConvSeqConfigStruct.triggerMask = 0U;
- adcConvSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityPositiveEdge;
- adcConvSeqConfigStruct.enableSingleStep = false;
- adcConvSeqConfigStruct.enableSyncBypass = false;
- adcConvSeqConfigStruct.interruptMode = kADC_InterruptForEachSequence;
- ADC_SetConvSeqAConfig(DEMO_ADC_BASE, &adcConvSeqConfigStruct);
- ADC_EnableConvSeqA(DEMO_ADC_BASE, true); /* Enable the conversion sequence A. */
- /* Clear the result register. */
- ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
- while (!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER, &adcResultInfoStruct))
- {
- }
- ADC_GetConvSeqAGlobalConversionResult(DEMO_ADC_BASE, &adcResultInfoStruct);
- }
复制代码
五.PC上位机部分
1.程序简介:
计算机上位机部分总共有两部分,包括上位机与单片机的串口通讯部分,以及上位机的三维显示部分。上位机程序部分全部用Python语言编程,实现了其与下位机单片机C语言之间的完美配合。上位机程序包括了四个文件:usart.py, xianshif.py, qtf.py, main.py其中调用了python中的第三方库有serial,time,sys, numpy,matplotlib,math,pyqt5。
2.程序原理:
usart.py文件中调用serial第三方库,更改串口号和波特率,实现单片机发送字符,上位机接收字符的功能,并将接受到的数据写入一个txt文件。xianshif.py 文件中调用qtf.py,用qtf.py中的SelectDialog类选择要读取的txt文件,导入文件后用matplotlib.pyplot分别绘制三维散点图(由于点比较多所以绘制出来的图形接近连续的三维立体图),三维雨图。
3.程序详解:
usart.py:先调用serial第三方库,编写recv函数,其功能为用serial.read_all()函数读取字符,并用return返回字符,每个字符读取时暂停20ms。接下来是主函数,serial.Serial(“com3”,115200,timeout=0.5),设置其接受数据为电脑的com3端口,波特率设置为115200(与单片机串口波特率相同);用isOpen()去查看是否成功打开串口;进入无限循环接受字符的模式,将接收到的四位字符打包成一个字符串,由于接受的顺序原因,需要将字符串对称调换,将所有的四位字符串转化为一个列表的格式,当接受到单片机发送过来的结束指令“X”字符时,将列表转换成字符串的形式储存在txt文件中,然后用sys.exit()函数退出主程序。
qtf.py:调用pyqt5和os,sys第三方库。此程序包含两个类,第一个类SelectDialog()为选择文件的对话框,其中changepath()方法为启动选择文件的界面,initUi()方法可以作为显示调用哪个文件以及最终的确认;第二个类Example(),包含两个方法,一个initUi()是显示主窗口的方法(其中包含一个菜单方法,可以通过点击菜单选项退出程序),center()为让窗口居中显示的方法。
Xianshif.py:调用numpy,matplotlib,math第三方库,以及qtf.py模块。程序先建立一个分成两部分,并且大小确定的画板;用pyqt5选择要调用的文件名称,储存为字符串,然后再用withopen()打开这个文件,然后逐行读取储存为数组a,然后用meshgrid()函数生成了绘制雨图所用到的x,y坐标,通过中间的一步步转换,可以最后求出三维散点图和三维雨图所对应的每个点的坐标,然后三维点图可以通过scatter()绘制,而三维雨图可以通过plot_surface()方法去绘制。(此程序还有一个闪光点,将一个二维平面卷起来变成三维图,并且在不用知道txt文件的行数和列数的条件下,可以在读取文件的时候自行判断,详情见程序。)
六.作品总结
本作品基本实现了上述流程图中的功能。但在开发过程中遭遇GND与3V3短接,板子直接冒烟,虽抢救及时,但板子失去带WIFI模块的能力,连上模块后电压会被拉低,然后系统失去响应。调试ADC模块真的不容易,参考很多文件,效果一直不太理想。本作品使用的霍尔传感器在工作中输出压差在70mV左右,要想获得更好的结果则需要外加放大器和滤波电路。由于信号类似于正弦信号,滤波效果不太理想,感兴趣的朋友建议尝试锁相放大器,求互相关函数可以得到较好效果。附完整程序,包括开发板代码和PC机客户端源程序。(开发板工程文件在“LPC双核挑战赛 Litthins团队作品\LPC54114J256\boards\lpcxpresso54114\multicore_examples\hello_world”)。
LPC双核挑战赛 Litthins团队作品 高频信号发生器设计.zip
(141.51 KB, 下载次数: 9)
|