|
普冉的M0系列MCU PY32F030K28自带的LED数码管驱动,省去了外部驱动IC。本例程演示通过模拟输入PA7引脚采集NTC(热敏电阻)电压计算对应温度并驱动四位LED数码管显示。
- /**
- ******************************************************************************
- * 文件名程: main.c
- * 作 者: 邓凯哥
- * 功 能: 主函数
- * 硬 件: PY32F030K28-StartKit-V0.1
- * 软件版本 V0.0.1(2024/4/16 16:02)
- ******************************************************************************
- **/
- #include "main.h"
- #include "ntc.h"
- #include "timepare.h"
- #define LED_DISP_c 0x61 //温度符号小c
- /* Private variables ---------------------------------------------------------*/
- const uint8_t dispArr[] = {LL_LED_DISP_0, LL_LED_DISP_1, LL_LED_DISP_2, LL_LED_DISP_3, LL_LED_DISP_4, \
- LL_LED_DISP_5, LL_LED_DISP_6, LL_LED_DISP_7, LL_LED_DISP_8, LL_LED_DISP_9
- };
- int32_t acc_adcval,mean_value;
- uint32_t ADC1_Datas[128];
- int16_t ADC_ConverDone,adc_count,tempval;
- /* Private user code ---------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- static void APP_SystemClockConfig(void);
- static void APP_AdcConfig(void);
- static void APP_AdcEnable(void);
- static void APP_AdcCalibrate(void);
- static void APP_ConfigLed(void);
- static void ADC1_DMA_Config(void);
- static void APP_ConfigUsart1(void);
- /******************************************************************************
- **函数信息 :System_Tick(uint32_t Ticks)
- **功能描述 :系统嘀嗒时钟配置
- **输入参数 :Ticks 频率
- **输出参数 :无
- **说 明 :
- ******************************************************************************/
- void System_Tick(uint32_t Ticks)
- {
- SysTick->LOAD = (uint32_t)((SystemCoreClock / Ticks) - 1UL); /* set reload register */
- SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
- SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
- SysTick_CTRL_TICKINT_Msk |
- SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */
- }
- /******************************************************************************
- **函数信息 :fputc( int data, FILE *f )
- **功能描述 :重定向fputc函数
- **输入参数 :data 要打印字符 , *f 文件指针
- **输出参数 :无
- **说 明 :
- ******************************************************************************/
- struct __FILE
- {
- int handle;
- };
- FILE __stdout;
- int fputc(int data, FILE *f)
- {
- /* Send a byte to USART */
- LL_USART_TransmitData8(USART1, data);
- while (!LL_USART_IsActiveFlag_TC(USART1));
- LL_USART_ClearFlag_TC(USART1);
- return (data);
- }
- /**
- * @brief 应用程序入口函数.
- * @retval int
- */
- int main(void)
- {
- /* 配置系统时钟 */
- APP_SystemClockConfig();
-
- /* 配置USART1相关参数 */
- APP_ConfigUsart1();
-
- /* ADC复位 */
- LL_ADC_Reset(ADC1);
- /* ADC模块时钟使能 */
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);
- /* ADC校准 */
- APP_AdcCalibrate();
- /* 配置ADC相关参数 */
- APP_AdcConfig();
-
- /* 配置ADC DMA参数 */
- ADC1_DMA_Config();
-
- /* 配置LED相关参数 */
- APP_ConfigLed();
- /* 使能ADC */
- APP_AdcEnable();
- /* 开始ADC转换(如果是软件触发则直接开始转换) */
- LL_ADC_REG_StartConversion(ADC1);
-
- /* 开启系统嘀嗒定时器 */
- System_Tick(1000);
- while (1)
- {
-
- if( TimePare.Tim1ms_flag == 1 ) //1ms任务
- {
- TimePare.Tim1ms_flag = 0;
- if( ++TimePare.Tim10ms_count >= 10 )
- {
- TimePare.Tim10ms_count = 0;
- TimePare.Tim10ms_flag = 1;
- }
-
- if( ++TimePare.Tim50ms_count >= 50 )
- {
- TimePare.Tim50ms_count = 0;
- TimePare.Tim50ms_flag = 1;
- }
- }
-
-
-
- if( TimePare.Tim10ms_flag == 1 ) //10ms 任务
- {
-
- TimePare.Tim10ms_flag = 0;
- if( ++TimePare.Tim100ms_count >= 10 )
- {
- TimePare.Tim100ms_count = 0;
- TimePare.Tim100ms_flag = 1;
- }
-
- if( ++TimePare.Tim200ms_count >= 20 )
- {
- TimePare.Tim200ms_count = 0;
- TimePare.Tim200ms_flag = 1;
- }
- }
-
-
- if( TimePare.Tim50ms_flag == 1 ) //50ms 任务
- {
-
- TimePare.Tim50ms_flag = 0;
- }
-
- if( TimePare.Tim100ms_flag == 1 ) //100ms 任务
- {
-
- TimePare.Tim100ms_flag = 0;
- if( ++TimePare.Tim500ms_count >= 5 )
- {
- TimePare.Tim500ms_count = 0;
- TimePare.Tim500ms_flag = 1;
- }
- }
-
- if( TimePare.Tim200ms_flag == 1 ) //200ms 任务
- {
- TimePare.Tim200ms_flag = 0;
- }
-
- if( TimePare.Tim500ms_flag == 1 ) //500ms 任务
- {
- ///显示NTC温度
- // LL_LED_SetDisplayValue(LED, LL_LED_COM0, dispArr[(tempval) /100]);
- LL_LED_SetDisplayValue(LED, LL_LED_COM1, dispArr[(tempval) %100/10]);
- LL_LED_SetDisplayValue(LED, LL_LED_COM2, dispArr[(tempval) %100%10]);
- LL_LED_SetDisplayValue(LED, LL_LED_COM3, LED_DISP_c);
-
- printf("ADC_VALUE = %d, NTC_VALUE = %d\r\n",mean_value, tempval); //串口打印ADC数值和NTC温度值
-
- TimePare.Tim500ms_flag = 0;
- if( ++TimePare.Tim1s_count >= 2 )
- {
- TimePare.Tim1s_count = 0;
- TimePare.Tim1s_flag = 1;
- }
- }
-
- if( TimePare.Tim1s_flag == 1 ) //1000ms 任务
- {
- TimePare.Tim1s_flag = 0;
- }
- }
- }
- /**
- * @brief 系统时钟配置函数
- * @param 无
- * @retval 无
- */
- static void APP_SystemClockConfig(void)
- {
- /* 使能HSI */
- LL_RCC_HSI_Enable();
- LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz);
- while(LL_RCC_HSI_IsReady() != 1)
- {
- }
- /* 设置 AHB 分频*/
- LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
- /* 配置HSISYS作为系统时钟源 */
- LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSISYS);
- while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSISYS)
- {
- }
- /* 设置 APB1 分频*/
- LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
- LL_Init1msTick(24000000);
- /* 更新系统时钟全局变量SystemCoreClock(也可以通过调用SystemCoreClockUpdate函数更新) */
- LL_SetSystemCoreClock(24000000);
- }
- /**
- * @brief USART配置函数
- * @param USARTx:USART模块,可以是USART1、USART2
- * @retval 无
- */
- static void APP_ConfigUsart1(void)
- {
- /*使能GPIOA时钟*/
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
- /*使能USART1时钟*/
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_USART1);
- /*GPIOA配置*/
- LL_GPIO_InitTypeDef GPIO_InitStruct;
- /*选择PA9引脚*/
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
- /*选择复用模式*/
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- /*选择输出速度*/
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- /*选择输出模式*/
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- /*选择上拉*/
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- /*复用为USART1功能*/
- GPIO_InitStruct.Alternate = LL_GPIO_AF1_USART1;
- /*GPIOA初始化*/
- LL_GPIO_Init(GPIOA,&GPIO_InitStruct);
- /*选择PA10引脚*/
- GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
- /*复用为USART1功能*/
- GPIO_InitStruct.Alternate = LL_GPIO_AF1_USART1;
- /*GPIOA初始化*/
- LL_GPIO_Init(GPIOA,&GPIO_InitStruct);
- /*配置USART功能*/
- LL_USART_InitTypeDef USART_InitStruct;
- /*设置波特率*/
- USART_InitStruct.BaudRate = 9600;
- /*设置数据长度*/
- USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
- /*停止位*/
- USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
- /*设置校验位*/
- USART_InitStruct.Parity = LL_USART_PARITY_NONE;
- USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
- USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
- USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
- /*USART1初始化*/
- LL_USART_Init(USART1, &USART_InitStruct);
- /*配置为全双工异步模式*/
- LL_USART_ConfigAsyncMode(USART1);
- /*使能UART1模块*/
- LL_USART_Enable(USART1);
- }
- /**
- * @brief ADC校准函数
- * @param 无
- * @retval 无
- */
- static void APP_AdcCalibrate(void)
- {
- __IO uint32_t wait_loop_index = 0;
- __IO uint32_t backup_setting_adc_dma_transfer = 0;
- #if (USE_TIMEOUT == 1)
- uint32_t Timeout = 0;
- #endif
- if (LL_ADC_IsEnabled(ADC1) == 0)
- {
- /* 校准时关闭ADC的DMA配置 */
- backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(ADC1);
- LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);
- /* 使能校准 */
- LL_ADC_StartCalibration(ADC1);
- #if (USE_TIMEOUT == 1)
- Timeout = ADC_CALIBRATION_TIMEOUT_MS;
- #endif
- while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0)
- {
- #if (USE_TIMEOUT == 1)
- /* 检测校准是否超时 */
- if (LL_SYSTICK_IsActiveCounterFlag())
- {
- if(Timeout-- == 0)
- {
- }
- }
- #endif
- }
- /* ADC校准结束和使能ADC之间的延时最低4个ADC Clock */
- LL_mDelay(1);
- /* 还原ADC的DMA配置 */
- LL_ADC_REG_SetDMATransfer(ADC1, backup_setting_adc_dma_transfer);
- }
- }
- /**
- * @brief ADC配置函数
- * @param 无
- * @retval 无
- */
- static void APP_AdcConfig(void)
- {
- /* 使能GPIOA时钟 */
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
- /* 配置管脚PA7为模拟输入 */
- LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ANALOG);
- /* ADC通道和时钟源需在ADEN=0时配置,其余的需在ADSTART=0时配置 */
- /* 配置内部转换通道 */
- LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_NONE);
- /* 设置ADC时钟 */
- LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_SYNC_PCLK_DIV2);
- /* 设置12位分辨率 */
- LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);
- /* 设置数据右对齐 */
- LL_ADC_SetResolution(ADC1, LL_ADC_DATA_ALIGN_RIGHT);
- /* 设置低功耗模式无 */
- LL_ADC_SetLowPowerMode(ADC1, LL_ADC_LP_MODE_NONE);
- /* 设置通道转换时间 */
- LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5);
- /* 设置触发源为Software */
- LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE);
- /* 设置转换模式为连续转换 */
- LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_CONTINUOUS);
- /* 设置DMA模式为循环 */
- LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
- /* 设置过载管理模式为覆盖上一个值 */
- LL_ADC_REG_SetOverrun(ADC1, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
- /* 使用PA7 ADC通道7,扫描方向必须为向上 */
- LL_ADC_REG_SetSequencerScanDirection(ADC1,LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);
- /* 设置非连续模式为不使能 */
- LL_ADC_REG_SetSequencerDiscont(ADC1, LL_ADC_REG_SEQ_DISCONT_DISABLE);
- /* 设置通道7为转换通道 */
- LL_ADC_REG_SetSequencerChannels(ADC1,LL_ADC_CHANNEL_7);
- }
- /**
- * @brief ADC使能函数
- * @param 无
- * @retval 无
- */
- static void APP_AdcEnable(void)
- {
- /* 使能ADC */
- LL_ADC_Enable(ADC1);
- /* 使能ADC 稳定时间,最低8个ADC Clock */
- LL_mDelay(1);
- }
- /**
- * @brief 配置LED数码管
- * @param 无
- * @retval 无
- */
- static void APP_ConfigLed(void)
- {
- /* 使能时钟 */
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LED);
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- /* 配置 PB3, PB4, PB5 为 com1 com2 com3 */
- GPIO_InitStruct.Pin = LL_GPIO_PIN_3 | LL_GPIO_PIN_4 | LL_GPIO_PIN_5;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
- LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- /* 配置 PA15 为 com0 */
- GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* 配置 PA0, PA1, PA2, PA3, PA4, PA5, PA6 为 SEG B C D E F G DP */
- GPIO_InitStruct.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3 | \
- LL_GPIO_PIN_4 | LL_GPIO_PIN_5 | LL_GPIO_PIN_6;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_3;
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* 配置 PB8 为 SEG A */
- GPIO_InitStruct.Pin = LL_GPIO_PIN_8;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_3;
- LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- /* 设置 LED COM 驱动能力 */
- LL_LED_SetComDrive(LED, LL_LED_COMDRIVE_LOW);
- /* 设置 COM 打开数 */
- LL_LED_SetComNum(LED, LL_LED_COMSELECT_4COM);
- /* 设置 LED 预分频值 */
- LL_LED_SetPrescaler(LED, 9);
- /* 设置 LED 点亮和切换时间 */
- LL_LED_SetLightAndDeadTime(LED, 0xf0, 0x10);
- /* 使能 LED */
- LL_LED_Enable(LED);
- }
- /******************************************************************************
- **函数信息 : ADC1_DMA_Config(void)
- **功能描述 :ADC1 DMA通道配置
- **输入参数 :无
- **输出参数 :无
- **说 明 :
- ******************************************************************************/
- void ADC1_DMA_Config()
- {
- /* 使能DMA1 时钟 */
- LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
- /* 使能syscfg 时钟 */
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
- /* ADC对应通道LL_DMA_CHANNEL_1 */
- SET_BIT(SYSCFG->CFGR3, 0x0);
- /* 配置DMA传输方向为外设到存储器 */
- LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
- /* 配置DMA优先级为高 */
- LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_HIGH);
- /* 配置DMA循环模式 */
- LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);
- /* 配置DMA外设地址不变模式 */
- LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
- /* 配置DMA存储地址自增模式 */
- LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
- /* 配置DMA外设传输方式为字 */
- LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_WORD);
- /* 配置DMA存储器传输方式为字 */
- LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_WORD);
- /* 配置DMA传输长度为128 */
- LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 128);
- /* 配置DMA外设和存储器的地址 */
- LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC1->DR,\
- (uint32_t)ADC1_Datas, LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1));
- /* 使能DMA传输完成中断 */
- LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
- /* DMA中断配置 */
- NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
- NVIC_EnableIRQ(DMA1_Channel1_IRQn);
- /* 使能DMA */
- LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
- }
- /******************************************************************************
- **函数信息 : ADC_DMATransferCompleteCallback(void)
- **功能描述 :ADC中断回调
- **输入参数 :无
- **输出参数 :无
- **说 明 :
- ******************************************************************************/
- void ADC_DMATransferCompleteCallback()
- {
- uint8_t i;
- acc_adcval = 0;
- for( i=0; i<128; i++)
- {
- acc_adcval += ADC1_Datas[i];
- }
- mean_value = acc_adcval >>7; //求128次ADC采样的平均值,用移位比除法运算更高效
- tempval = ADC_Get_TempValue( mean_value);
- }
- /**
- * @brief 错误执行函数
- * @param 无
- * @retval 无
- */
- void APP_ErrorHandler(void)
- {
- /* 无限循环 */
- while (1)
- {
- }
- }
- #ifdef USE_FULL_ASSERT
- /**
- * @brief 输出产生断言错误的源文件名及行号
- * @param file:源文件名指针
- * @param line:发生断言错误的行号
- * @retval 无
- */
- void assert_failed(uint8_t *file, uint32_t line)
- {
- /* 用户可以根据需要添加自己的打印信息,
- 例如: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* 无限循环 */
- while (1)
- {
- }
- }
- #endif /* USE_FULL_ASSERT */
复制代码
代码下载:
|
评分
-
查看全部评分
|