学习记录(四)定时器发PWM波、定时器触发ADC通过DMA存入内存,串口发送温度传感器校正值。——stm32

4.1.1 调时钟,要选外部高速源HSE(24MHz晶振),右边填170MHz后Cube软件会自动生成选择方案。

 

4.1.2 先用定时器TIM1产生一个20KHz,正占空比为20%的PWM波。配置如下:使能内部时钟、打开通道1、参数如图配置。预分频PSC和Counter Period实际计算会算上0所以要-1。为方便配占空比设计数周期为10次,Pulse设为2。

频率为 170MHz/850/10 = 20KHz。

 

在PWM mode 1、Upcounting计数模式下,Counter Period参数存入寄存器ARR(Auto Reload Register),Pulse参数存入寄存器CCR(Capture Compare Register),参照用户手册中下图。本例中计数值为9,Pulse值为2,则0~9中小于2的部分0、1为高电平,2~9为低电平,使正占空比为20%。

 

4.1.3 MDK中代码需调用此函数打开PWM输出。

 

4.1.4 示波器验证效果成功实现。

 

4.2 再用定时器以1KHz频率触发ADC转换芯片内部温度传感器数据,用DMA存储,并通过串口发送温度校正值。

  4.2.1 打开TIM6调参数使频率为 170MHz/170/1000 = 1KHz。然后打开ADC1的Temperature Sensor和Vrefint(内部参考电压)通道,设为扫描、非连续模式,用TIM6触发。

 

4.2.2 添加DMA用于将ADC采集数据存入内存,设为循环模式,因为ADC1是12位所以内存地址每次增加16位,设为Half Word。DMA将会在内存某处环形缓冲区(设为 u16 ADC_Data[20] ,两个通道各取十次测量值,计算中/10取平均值)循环往复写入数据,如图是一次循环的内存快照,下次循环从base重新开始写入。

//取数据部分代码
	ADC_TS = 0;
	ADC_VREFINT = 0;

	for(u8 i=0; i<20; ){
		ADC_TS += ADC_Data[i++];
		ADC_VREFINT += ADC_Data[i++];
	}

	ADC_TS /= 10;
	ADC_VREFINT /= 10;

再在main()中调用此函数即可打开DMA:

 

4.2.2 MDK中代码需要调用这个函数打开定时器TIM6。

 

4.2.3 ①在用户手册中研究温度校正和内部参考电压校正,得到以下两个公式:

②在stm32g4xx_II_adc.c中找到以上两公式的计算宏

/**
  * @brief  Helper macro to calculate analog reference voltage (Vref+)
  *         (unit: mVolt) from ADC conversion data of internal voltage
  *         reference VrefInt.
  * @note   Computation is using VrefInt calibration value
  *         stored in system memory for each device during production.
  * @note   This voltage depends on user board environment: voltage level
  *         connected to pin Vref+.
  *         On devices with small package, the pin Vref+ is not present
  *         and internally bonded to pin Vdda.
  * @note   On this STM32 series, calibration data of internal voltage reference
  *         VrefInt corresponds to a resolution of 12 bits,
  *         this is the recommended ADC resolution to convert voltage of
  *         internal voltage reference VrefInt.
  *         Otherwise, this macro performs the processing to scale
  *         ADC conversion data to 12 bits.
  * @param  __VREFINT_ADC_DATA__ ADC conversion data (resolution 12 bits)
  *         of internal voltage reference VrefInt (unit: digital value).
  * @param  __ADC_RESOLUTION__ This parameter can be one of the following values:
  *         @arg @ref LL_ADC_RESOLUTION_12B
  *         @arg @ref LL_ADC_RESOLUTION_10B
  *         @arg @ref LL_ADC_RESOLUTION_8B
  *         @arg @ref LL_ADC_RESOLUTION_6B
  * @retval Analog reference voltage (unit: mV)
  */
#define __LL_ADC_CALC_VREFANALOG_VOLTAGE(__VREFINT_ADC_DATA__,\
                                         __ADC_RESOLUTION__)                   \
  (((uint32_t)(*VREFINT_CAL_ADDR) * VREFINT_CAL_VREF)                          \
   / __LL_ADC_CONVERT_DATA_RESOLUTION((__VREFINT_ADC_DATA__),                  \
                                      (__ADC_RESOLUTION__),                    \
                                      LL_ADC_RESOLUTION_12B))

/**
  * @brief  Helper macro to calculate the temperature (unit: degree Celsius)
  *         from ADC conversion data of internal temperature sensor.
  * @note   Computation is using temperature sensor calibration values
  *         stored in system memory for each device during production.
  * @note   Calculation formula:
  *           Temperature = ((TS_ADC_DATA - TS_CAL1)
  *                           * (TS_CAL2_TEMP - TS_CAL1_TEMP))
  *                         / (TS_CAL2 - TS_CAL1) + TS_CAL1_TEMP
  *           with TS_ADC_DATA = temperature sensor raw data measured by ADC
  *                Avg_Slope = (TS_CAL2 - TS_CAL1)
  *                            / (TS_CAL2_TEMP - TS_CAL1_TEMP)
  *                TS_CAL1   = equivalent TS_ADC_DATA at temperature
  *                            TEMP_DEGC_CAL1 (calibrated in factory)
  *                TS_CAL2   = equivalent TS_ADC_DATA at temperature
  *                            TEMP_DEGC_CAL2 (calibrated in factory)
  *         Caution: Calculation relevancy under reserve that calibration
  *                  parameters are correct (address and data).
  *                  To calculate temperature using temperature sensor
  *                  datasheet typical values (generic values less, therefore
  *                  less accurate than calibrated values),
  *                  use helper macro @ref __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS().
  * @note   As calculation input, the analog reference voltage (Vref+) must be
  *         defined as it impacts the ADC LSB equivalent voltage.
  * @note   Analog reference voltage (Vref+) must be either known from
  *         user board environment or can be calculated using ADC measurement
  *         and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE().
  * @note   On this STM32 series, calibration data of temperature sensor
  *         corresponds to a resolution of 12 bits,
  *         this is the recommended ADC resolution to convert voltage of
  *         temperature sensor.
  *         Otherwise, this macro performs the processing to scale
  *         ADC conversion data to 12 bits.
  * @param  __VREFANALOG_VOLTAGE__  Analog reference voltage (unit: mV)
  * @param  __TEMPSENSOR_ADC_DATA__ ADC conversion data of internal
  *                                 temperature sensor (unit: digital value).
  * @param  __ADC_RESOLUTION__      ADC resolution at which internal temperature
  *                                 sensor voltage has been measured.
  *         This parameter can be one of the following values:
  *         @arg @ref LL_ADC_RESOLUTION_12B
  *         @arg @ref LL_ADC_RESOLUTION_10B
  *         @arg @ref LL_ADC_RESOLUTION_8B
  *         @arg @ref LL_ADC_RESOLUTION_6B
  * @retval Temperature (unit: degree Celsius)
  */
#define __LL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\
                                  __TEMPSENSOR_ADC_DATA__,\
                                  __ADC_RESOLUTION__)                              \
  (((( ((int32_t)((__LL_ADC_CONVERT_DATA_RESOLUTION((__TEMPSENSOR_ADC_DATA__),     \
                                                    (__ADC_RESOLUTION__),          \
                                                    LL_ADC_RESOLUTION_12B)         \
                   * (__VREFANALOG_VOLTAGE__))                                     \
                  / TEMPSENSOR_CAL_VREFANALOG)                                     \
        - (int32_t) *TEMPSENSOR_CAL1_ADDR)                                         \
     ) * (int32_t)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP)                    \
    ) / (int32_t)((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) \
   ) + TEMPSENSOR_CAL1_TEMP                                                        \
  )

③通过串口打印结果,仍用TaskProcess()函数,以下是部分定义和实际功能函数代码。

//部分定义
/* USER CODE BEGIN PTD */
#define MCL_MAX 2
#define __VREFINT_ADC_DATA__ (ADC_VREFINT/10)
#define __ADC_RESOLUTION__ (LL_ADC_RESOLUTION_12B)
#define __VREFANALOG_VOLTAGE__ (__HAL_ADC_CALC_VREFANALOG_VOLTAGE(__VREFINT_ADC_DATA__,\
                                                                  __ADC_RESOLUTION__))
#define __TEMPSENSOR_ADC_DATA__ (ADC_TS/10)
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
vu32 OSTick   = 0;
u16 ADC_Data[2*10];		//两组测十次取平均值.
u32 ADC_TS, ADC_VREFINT;

static void App_EndProcess(void);
void TimingDelay_Decrement(void);
void SetMacbRemarks(u16 dif);
static void TaskProcess(void);
void TP_Send(void);
/* USER CODE END PD */
void TP_Send(void)
{
	ADC_TS = 0;
	ADC_VREFINT = 0;

	for(u8 i=0; i<20; ){
		ADC_TS += ADC_Data[i++];
		ADC_VREFINT += ADC_Data[i++];
	}
	
	printf("TS_ADC_DATA = %d \n", (ADC_TS/10));
	printf("__VREFINT_ADC_DATA__ = %d \n", (ADC_VREFINT/10));
	printf("__HAL_ADC_CALC_VREFANALOG_VOLTAGE = %lu\n",         
            __HAL_ADC_CALC_VREFANALOG_VOLTAGE(__VREFINT_ADC_DATA__,\
                                              __ADC_RESOLUTION__));
	printf("__HAL_ADC_CALC_TEMPERATURE = %lu\n", 
            __HAL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\
                                       __TEMPSENSOR_ADC_DATA__,\
                                       __ADC_RESOLUTION__));
}  

4.2.4 在串口调试助手上验证结果:

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值