/** ****************************************************************************** * @file main.c * @author MCU Application Team * @brief Main program body ****************************************************************************** * @attention * *

© Copyright (c) 2023 Puya Semiconductor Co. * All rights reserved.

* * This software component is licensed by Puya under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** * @attention * *

© Copyright (c) 2016 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "py32f002bxx_ll_Start_Kit.h" /* Private define ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ unsigned int ADC_RE[4]; unsigned int ADC_CH1_CUSUM; unsigned int ADC_CH2_CUSUM; unsigned int ADC_CH3_CUSUM; unsigned int ADC_CH4_CUSUM; unsigned int ADC_CH1_RE; unsigned int ADC_CH2_RE; unsigned int ADC_CH3_RE; unsigned int ADC_CH4_RE; // uint8_t SPI_TxBuff[32] = { \ // 1,0xaa,2,0xaa,3,0xaa,4,0xaa,5,0xaa,\ // 1,0xaa,2,0xaa,3,0xaa,4,0xaa,5,0xaa,\ // 1,0xaa,2,0xaa,3,0xaa,4,0xaa,5,0xaa,\ // 1,0xaa // }; uint8_t SPI_TxBuff[32]; uint8_t SPI_TxIndex = 0; uint8_t SPI_RxBuff[32]; uint8_t SPI_RxIndex = 0; typedef struct { uint8_t HEAD; uint8_t len; uint8_t res[2]; uint32_t key; uint16_t lx; uint16_t ly; uint16_t rx; uint16_t ry; }ZKM_Keybuf_t; ZKM_Keybuf_t Send_buf; /* Private user code ---------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ static void APP_SystemClockConfig(void); static void APP_AdcEnable(void); static void APP_AdcCalibrate(void); static void APP_AdcConfig(void); static void APP_TimerInit(void); static void APP_Key_Init(void); static uint32_t APP_Read_Key_val(void); static void APP_FlashOBProgram(void); static void APP_ConfigSpi(void); static void APP_ConfigureEXTI(void); void *App_Memcpy(void *dst,const void *src,size_t size); uint16_t calculate_check_sum(void *buf, uint16_t len); /** * @brief Main program. * @param None * @retval int */ int main(void) { static uint32_t cont = 0; static uint32_t adc_cont = 0; /* Configure Systemclock */ APP_SystemClockConfig(); /* Configure ADC parameters */ APP_AdcConfig(); /* Initialize USART(for printf use) */ BSP_USART_Config(); printf("Delay:1000 mS \n\r"); // LL_mDelay(1000); printf("Delay End, program start \n\r"); APP_ConfigureEXTI(); /* Initialize TIM1 */ APP_TimerInit(); APP_Key_Init(); APP_ConfigSpi(); // memset(&Send_buf, 0, sizeof(ZKM_Keybuf_t)); printf("sizeof(ZKM_Keybuf_t):%d\n\r",sizeof(ZKM_Keybuf_t)); // LL_SPI_Enable(SPI1); while(1) { if(LL_ADC_IsActiveFlag_EOS(ADC1)==1) //4路ADC数据采集 { LL_ADC_ClearFlag_EOS(ADC1); ADC_CH1_CUSUM = ADC_CH1_CUSUM - (ADC_CH1_CUSUM>>3) +ADC_RE[0]; ADC_CH1_RE=ADC_CH1_CUSUM>>3; ADC_CH2_CUSUM = ADC_CH2_CUSUM - (ADC_CH2_CUSUM>>3) +ADC_RE[1]; ADC_CH2_RE=ADC_CH2_CUSUM>>3; ADC_CH3_CUSUM = ADC_CH3_CUSUM - (ADC_CH3_CUSUM>>3) +ADC_RE[2]; ADC_CH3_RE=ADC_CH3_CUSUM>>3; ADC_CH4_CUSUM = ADC_CH4_CUSUM - (ADC_CH4_CUSUM>>3) +ADC_RE[3]; ADC_CH4_RE=ADC_CH4_CUSUM>>3; // printf("adc: %d, %d, %d, %d ,%x\n\r", ADC_CH1_RE, ADC_CH2_RE, ADC_CH3_RE, ADC_CH4_RE, APP_Read_Key_val()); adc_cont++; Send_buf.HEAD = 0xA5; Send_buf.len = 16; Send_buf.res[0] = 0; Send_buf.res[1] = 0; Send_buf.key = APP_Read_Key_val(); Send_buf.lx = ADC_CH1_RE; Send_buf.ly = ADC_CH2_RE; Send_buf.rx = ADC_CH3_RE; Send_buf.ry = ADC_CH4_RE; App_Memcpy(SPI_TxBuff, &Send_buf, 16); SPI_TxBuff[16] = calculate_check_sum(SPI_TxBuff, 16); } if(cont >= 100000){ printf("adc_cont:%d, %x\n\r",adc_cont, APP_Read_Key_val()); cont = 0; adc_cont = 0; }else{ cont++; } } } /** * @brief Configure ADC parameters * @param None * @retval None */ static void APP_AdcConfig(void) { /* Enable ADC1 clock */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1); /* Enable GPIOA clock */ LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); /* Configure PA7 pin in analog input mode */ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ANALOG); /* Configure PA6 pin in analog input mode */ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_ANALOG); /* Configure PA6 pin in analog input mode */ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_ANALOG); /* Configure PA6 pin in analog input mode */ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ANALOG); /* Set ADC clock to pclk/4 */ LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_SYNC_PCLK_DIV4); /* Set ADC resolution to 12 bit */ LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B); /* ADC conversion data alignment: right aligned */ LL_ADC_SetDataAlignment(ADC1, LL_ADC_DATA_ALIGN_RIGHT); /* No ADC low power mode activated */ LL_ADC_SetLowPowerMode(ADC1, LL_ADC_LP_MODE_NONE); /* Sampling time 239.5 ADC clock cycles */ LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5); /* ADC regular group conversion trigger from external IP: TIM1 TRGO. */ LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_EXT_TIM1_TRGO); /* Set Trigger edge to rising edge */ LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_RISING); /* Set ADC conversion mode to single mode: one conversion per trigger */ LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_SINGLE); /* ADC regular group behavior in case of overrun: data overwritten */ LL_ADC_REG_SetOverrun(ADC1, LL_ADC_REG_OVR_DATA_OVERWRITTEN); /* Disable ADC regular group sequencer discontinuous mode */ LL_ADC_REG_SetSequencerDiscont(ADC1, LL_ADC_REG_SEQ_DISCONT_DISABLE); /* Set channel 1/2/3/4/vrefint as conversion channel */ LL_ADC_REG_SetSequencerChannels(ADC1, LL_ADC_CHANNEL_4); LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_3); LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_2); LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_1); // LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_VREFINT); /* Dose not enable internal conversion channel */ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT ); /* Enable EOC IT */ LL_ADC_EnableIT_EOC(ADC1); NVIC_SetPriority(ADC_COMP_IRQn,1); NVIC_EnableIRQ(ADC_COMP_IRQn); /* ADC automatic self-calibration */ APP_AdcCalibrate(); /* Enable ADC */ APP_AdcEnable(); /* Start ADC conversion (if it is software triggered then start conversion directly) */ LL_ADC_REG_StartConversion(ADC1); } /** * @brief ADC calibration program. * @param None * @retval None */ static void APP_AdcCalibrate(void) { #if (USE_TIMEOUT == 1) uint32_t Timeout = 0; #endif if (LL_ADC_IsEnabled(ADC1) == 0) { /* Enable ADC calibration */ LL_ADC_StartCalibration(ADC1); #if (USE_TIMEOUT == 1) Timeout = ADC_CALIBRATION_TIMEOUT_MS; #endif while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0) { #if (USE_TIMEOUT == 1) /* Detects if the calibration has timed out */ if (LL_SYSTICK_IsActiveCounterFlag()) { if(Timeout-- == 0) { } } #endif } /* The delay between the end of ADC calibration and ADC enablement is at least 4 ADC clocks */ LL_mDelay(1); } } /** * @brief Enable ADC. * @param None * @retval None */ static void APP_AdcEnable(void) { /* Enable ADC */ LL_ADC_Enable(ADC1); /* The delay between ADC enablement and ADC stabilization is at least 8 ADC clocks */ LL_mDelay(1); } /** * @brief TIM1 configuration program. * @param None * @retval None */ static void APP_TimerInit() { /* Enable TIM1 clock */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1); /* Set TIM1 prescale */ LL_TIM_SetPrescaler(TIM1,6); /* Set TIM1 auto-reload value */ LL_TIM_SetAutoReload(TIM1, 3000); /* TIM1 Update event is used as trigger output */ LL_TIM_SetTriggerOutput(TIM1,LL_TIM_TRGO_UPDATE); /* Enable TIM1 */ LL_TIM_EnableCounter(TIM1); } /** * @brief Configure Systemclock * @param None * @retval None */ static void APP_SystemClockConfig(void) { /* Enable SYSCFG clock and PWR clock */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); /* Enable HSI */ LL_RCC_HSI_Enable(); while(LL_RCC_HSI_IsReady() != 1) { } /* Set AHB divider: HCLK = SYSCLK */ LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); /* HSISYS used as SYSCLK clock source */ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSISYS); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSISYS) { } /* Set APB1 divider */ LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); LL_Init1msTick(24000000); /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */ LL_SetSystemCoreClock(24000000); } /** * @brief Option byte program * @param None * @retval None */ static void APP_FlashOBProgram(void) { FLASH_OBProgramInitTypeDef OBInitCfg; /* Unlock the Flash to enable the flash control register access */ HAL_FLASH_Unlock(); /* Unlock the Flash to enable access to the part of flash control register that is about option byte */ HAL_FLASH_OB_Unlock(); /* Initialize FLASH Option Bytes PROGRAM structure */ OBInitCfg.OptionType = OPTIONBYTE_USER; OBInitCfg.USERType = OB_USER_BOR_EN | OB_USER_BOR_LEV | OB_USER_IWDG_SW | OB_USER_IWDG_STOP | OB_USER_SWD_NRST_MODE; OBInitCfg.USERConfig = OB_BOR_DISABLE | OB_BOR_LEVEL_3p1_3p2 | OB_IWDG_SW | OB_IWDG_STOP_ACTIVE | OB_SWD_PB6_GPIO_PC0 ; /* Execute option byte program */ HAL_FLASH_OBProgram(&OBInitCfg); /* Lock the Flash to disable the flash control register access */ HAL_FLASH_Lock(); /* Lock the Flash to disable access to the part of flash control register that is about option byte */ HAL_FLASH_OB_Lock(); /* Generate a reset and let option byte reload */ HAL_FLASH_OB_Launch(); } void APP_GPIO_Init(GPIO_TypeDef *GPIOx, uint32_t PinMask) { // LL_GPIO_SetPinMode(GPIOx, PinMask, LL_GPIO_MODE_INPUT); // LL_GPIO_SetPinPull(GPIOx, PinMask, LL_GPIO_PULL_UP); LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = PinMask; GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOx, &GPIO_InitStruct); } void APP_Key_Init(void) { if(READ_BIT(FLASH->OPTR, OB_USER_SWD_NRST_MODE)!= OB_SWD_PB6_GPIO_PC0 ) { /* Option byte program */ APP_FlashOBProgram(); } LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC); APP_GPIO_Init(GPIOA, LL_GPIO_PIN_5); // APP_GPIO_Init(GPIOA, LL_GPIO_PIN_2); //TODO SWDIO 调试使用 // APP_GPIO_Init(GPIOB, LL_GPIO_PIN_6); APP_GPIO_Init(GPIOB, LL_GPIO_PIN_7); APP_GPIO_Init(GPIOB, LL_GPIO_PIN_5); // APP_GPIO_Init(GPIOB, LL_GPIO_PIN_4); APP_GPIO_Init(GPIOB, LL_GPIO_PIN_3); APP_GPIO_Init(GPIOB, LL_GPIO_PIN_2); APP_GPIO_Init(GPIOC, LL_GPIO_PIN_0); APP_GPIO_Init(GPIOC, LL_GPIO_PIN_1); } uint32_t APP_Read_Key_val(void) { uint32_t key_value = 0; if(LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5) == 0) key_value |= HW_KEY_R3; // if(LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_2) == 0) key_value |= HW_KEY_L3; // if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_6) == 0) key_value |= HW_KEY_B; if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_7) == 0) key_value |= HW_KEY_A; if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_5) == 0) key_value |= HW_KEY_M2; // if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_4) == 0) key_value |= HW_KEY_M1; if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_3) == 0) key_value |= HW_KEY_START; if(LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_2) == 0) key_value |= HW_KEY_SELECT; if(LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_0) == 0) key_value |= HW_KEY_Y; if(LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_1) == 0) key_value |= HW_KEY_X; return key_value; } static void APP_ConfigureEXTI(void) { /* Enable GPIOA clock */ LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); /* Configure PA0 as input mode */ LL_GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = LL_GPIO_PIN_1; GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Set EXTI0 to connected to PA0 pin */ LL_EXTI_SetEXTISource(LL_EXTI_CONFIG_PORTB,LL_EXTI_CONFIG_LINE1); /* Set EXTI0 to event patterns, falling edge trigger */ LL_EXTI_InitTypeDef EXTI_InitStruct; EXTI_InitStruct.Line = LL_EXTI_LINE_1; EXTI_InitStruct.LineCommand = ENABLE; EXTI_InitStruct.Mode = LL_EXTI_MODE_IT; EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING; LL_EXTI_Init(&EXTI_InitStruct); /* Enable and set EXTI line0 Interrupt to the lowest priority */ NVIC_SetPriority(EXTI0_1_IRQn, 1); NVIC_EnableIRQ(EXTI0_1_IRQn); } /** * @brief Set SPI1 fearures * @param None * @retval None */ static void APP_ConfigSpi(void) { LL_SPI_InitTypeDef SPI_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Enable SPI1 periphreal clock */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SPI1); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); /**SPI1 I/O configuration PB2 ------> SPI1_SCK PA1 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = LL_GPIO_PIN_0; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; GPIO_InitStruct.Alternate = LL_GPIO_AF_0; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_1; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_0; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_0; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_0; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Enable SPI1 interrupt request */ NVIC_SetPriority(SPI1_IRQn, 0); NVIC_EnableIRQ(SPI1_IRQn); /* Set SPI1 features */ SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; SPI_InitStruct.Mode = LL_SPI_MODE_SLAVE; SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV128; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; LL_SPI_Init(SPI1, &SPI_InitStruct); /* Configure SPI1 Transmission Interrupts */ /* Enable TXE interrupt request */ LL_SPI_EnableIT_TXE(SPI1); /* Enable RxNE interrupt request */ LL_SPI_EnableIT_RXNE(SPI1); /* Enable SPI1 Error interrupt request */ LL_SPI_EnableIT_ERR(SPI1); } /** * @brief SPI1 receive callback * @param None * @retval None */ void APP_SpiRxCallback(void) { /* Read data register to clear RxNE flag */ SPI_RxBuff[SPI_RxIndex++] = LL_SPI_ReceiveData8(SPI1); } /** * @brief SPI1 send callback * @param None * @retval None */ void APP_SpiTxCallback(void) { /* Write data register to clear TxE flag */ LL_SPI_TransmitData8(SPI1, SPI_TxBuff[SPI_TxIndex++]); // printf("t\n\r"); } /** * @brief SPI transfer error treatment callback * @param None * @retval None */ void APP_SpiTransferErrorCallback(void) { /* Disable RxNE interrupt request */ LL_SPI_DisableIT_RXNE(SPI1); /* Disable TXE interrupt request */ LL_SPI_DisableIT_TXE(SPI1); /* printf error notice */ printf("SPI Transfer Error\n\r"); } void APP_Spi_CS_EN(uint8_t en) { SPI_RxIndex = 0; SPI_TxIndex = 0; } /** * @brief Error handling function * @param None * @retval None */ void APP_ErrorHandler(void) { /* Infinite loop */ while (1) { } } void *App_Memcpy(void *dst,const void *src,size_t size) { char *psrc; //源地址 char *pdst; //目标地址 if(NULL == dst || NULL == src) { return NULL; } //源地址在前,对应上述情况2,需要自后向前拷贝 if((src < dst)&&(char *)src+size > (char *)dst) { psrc = (char *)src + size - 1; pdst = (char *)dst + size - 1; while(size--) { *pdst-- = *psrc--; } } else //源地址在后,对应上述第一种情况,直接逐个拷贝*pdst++=*psrc++即可 { psrc = (char *)src; pdst = (char *)dst; while(size--) { *pdst++ = *psrc++; } } return pdst; } uint16_t calculate_check_sum(void *buf, uint16_t len) { uint16_t i; uint16_t sum = 0; uint8_t *p; p = (uint8_t*)buf; //HEAD inglne , 100 -SUM for(i=0; i