NUC131演示如何通过PWM触发ADC。

本文详细介绍了一种利用PWM触发ADC采样的实现方法。通过设置PWM的周期与比较值,结合ADC的硬件触发条件,实现了精确控制ADC采样时刻的目的。文章通过具体的代码示例解释了如何配置PWM和ADC模块,以及如何观察PWM波形和ADC采样结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天我来讲讲PWM触发ADC的例程

/**************************************************************************** * @file main.c * @version V2.0

 * $Revision: 5 $
 * $Date: 14/06/30 4:51p $
 * @brief    Demonstrate how to trigger ADC by PWM.
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 *
 ******************************************************************************/
#include <stdio.h>
#include "NUC131.h"


#define PLL_CLOCK       50000000


/*---------------------------------------------------------------------------------------------------------*/
/* Define Function Prototypes                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
void SYS_Init(void); //系统初始化
void UART0_Init(void); //串口初始化
void ADC_PWMTrigTest_SingleOpMode(void); //ADC硬件触发测试


void SYS_Init(void) //选择时钟,选择模块,配置引脚 
{
/*---------------------------------------------------------------------------------------------------------*/ /* Init System Clock */ /*---------------------------------------------------------------------------------------------------------*/ /* Enable Internal RC 22.1184MHz clock */ CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk); //选择内部RC时钟 /* Waiting for Internal RC clock ready */ CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk); /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));//分频 /* Enable external XTAL 12MHz clock */ CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk); /* Waiting for external XTAL clock ready */ CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk); /* Set core clock as PLL_CLOCK from PLL */ CLK_SetCoreClock(PLL_CLOCK); /* Enable UART module clock */ CLK_EnableModuleClock(UART0_MODULE); /* Enable ADC module clock */ CLK_EnableModuleClock(ADC_MODULE); /* Enable PWM0 module clock */ CLK_EnableModuleClock(PWM0_MODULE); /* Select UART module clock source */ CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1)); /* Select PWM01 module clock source */ CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL3_PWM0_S_PCLK, 0); /* ADC clock source is 22.1184MHz, set divider to 7, ADC clock is 22.1184/7 MHz */ CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_CLKDIV_ADC(7)); /*---------------------------------------------------------------------------------------------------------*/ /* Init I/O Multi-function */ /*---------------------------------------------------------------------------------------------------------*/ /* Set GPB multi-function pins for UART0 RXD and TXD */ SYS->GPB_MFP &= ~(SYS_GPB_MFP_PB0_Msk | SYS_GPB_MFP_PB1_Msk);//配置串口引脚 SYS->GPB_MFP |= SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD; /* Disable the GPA0 - GPA3 digital input path to avoid the leakage current. */ GPIO_DISABLE_DIGITAL_PATH(PA, 0xF);//禁用GPA0 - GPA3数字输入路径以避免泄漏电流 /* Configure the GPA0 - GPA3 ADC analog input pins */ SYS->GPA_MFP &= ~(SYS_GPA_MFP_PA0_Msk | SYS_GPA_MFP_PA1_Msk | SYS_GPA_MFP_PA2_Msk | SYS_GPA_MFP_PA3_Msk) ;//配置GPA
//0至PA3位为ADC模拟输入引脚
SYS
->GPA_MFP |= SYS_GPA_MFP_PA0_ADC0 | SYS_GPA_MFP_PA1_ADC1 | SYS_GPA_MFP_PA2_ADC2 | SYS_GPA_MFP_PA3_ADC3 ;
//引脚复用
/* Configure the PA12 as PWM0 output pin */ SYS->GPA_MFP = (SYS->GPA_MFP & (~SYS_GPA_MFP_PA12_Msk));//配置PWM0的引脚
SYS
->GPA_MFP |= SYS_GPA_MFP_PA12_PWM0_CH0;//PWM0的0通道 } /*---------------------------------------------------------------------------------------------------------*/ /* Init UART */ /*---------------------------------------------------------------------------------------------------------*/ void UART0_Init()//复位,和打开串口模块 { /* Reset IP */ SYS_ResetModule(UART0_RST); /* Configure UART0 and set UART0 Baudrate */ UART_Open(UART0, 115200); } /*---------------------------------------------------------------------------------------------------------*/ /* Function: ADC_PWMTrigTest_SingleOpMode */ /* */ /* Parameters: */ /* None. */ /* */ /* Returns: */ /* None. */ /* */ /* Description: */ /* ADC hardware trigger test. ADC硬件触发测试。 */ /*---------------------------------------------------------------------------------------------------------*/ void ADC_PWMTrigTest_SingleOpMode()//这个得好好讲讲了 说明PWM是如何激发ADC进行读取的。 { printf("\n<<< PWM trigger test (Single mode) >>>\n"); /* Set the ADC operation mode as single, input mode as single-end and enable the analog input channel 2 */ ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, 0x1 << 2);
//将ADC操作模式设置为单一模式,输入模式为单端,并启用模拟输入通道2 打开ADC通道
/* Power on ADC module */ ADC_POWER_ON(ADC);
//#define ADC_POWER_ON(adc) ((adc)->ADCR |= ADC_ADCR_ADEN_Msk)
//Before starting A/D conversion function, ADEN bit (ADCR[0]) should be set to 1.在启动A / D转换功能之前,应将ADEN位(ADCR [0])设置为1。
/* Configure the hardware trigger condition and enable hardware trigger; PWM trigger delay: (4*10) system clock cycles*/ ADC_EnableHWTrigger(ADC, ADC_ADCR_TRGS_PWM, 0);//配置硬件触发条件并启用硬件触发; PWM触发延迟:(4 * 10)个系统时钟周期
/******************************************************************************************************************************************************
/*
/** * @brief Configure the hardware trigger condition and enable hardware trigger.配置硬件触发条件并启用硬件触发 * @param[in] adc The pointer of the specified ADC module.adc指定ADC模块的指针。 * @param[in] u32Source Decides the hardware trigger source. Valid values are: u32Source决定硬件触发源。 * - \ref ADC_ADCR_TRGS_STADC :A/D conversion is started by external STADC pin.A / D转换由外部STADC引脚启动 * - \ref ADC_ADCR_TRGS_PWM :A/D conversion is started by PWM.//A / D转换由PWM启动
* @param[in] u32Param ADC trigger by external pin, this parameter is used to set trigger condition. Valid values are://u32Param ADC由外部引脚触发,
//该参数用于设置触发条件。 * - \ref ADC_ADCR_TRGCOND_LOW_LEVEL :STADC Low level active. * - \ref ADC_ADCR_TRGCOND_HIGH_LEVEL :STADC High level active. * - \ref ADC_ADCR_TRGCOND_FALLING_EDGE :STADC Falling edge active. * - \ref ADC_ADCR_TRGCOND_RISING_EDGE :STADC Rising edge active. * @return None * @details Software should disable TRGEN (ADCR[8]) and ADST (ADCR[11]) before change TRGS(ADCR[5:4]). */
void ADC_EnableHWTrigger(ADC_T *adc, uint32_t u32Source, uint32_t u32Param) { ADC->ADCR &= ~(ADC_ADCR_TRGS_Msk | ADC_ADCR_TRGCOND_Msk | ADC_ADCR_TRGEN_Msk); ADC->ADCR |= u32Source | u32Param | ADC_ADCR_TRGEN_Msk; return; }
*******************************************************************************************************************************************************/ /* Clear the A/D interrupt flag for safe */ ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);//清除A / D中断标志以确保安全 /* Center-aligned type 该宏设置PWM对齐类型*/ PWM_SET_ALIGNED_TYPE(PWM0, PWM_CH_0_MASK, PWM_CENTER_ALIGNED);//中心对齐的类型
/******************************************************************************************************************************************************
/** * @brief This macro set the PWM aligned type * @param[in] pwm The pointer of the specified PWM module * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. Every two channels share the same setting. * Bit 0 represents channel 0, bit 1 represents channel 1... * @param[in] u32AlignedType PWM aligned type, valid values are: * - \ref PWM_EDGE_ALIGNED * - \ref PWM_CENTER_ALIGNED * @return None * @details This macro is used to set the PWM aligned type of specified channel(s). * \hideinitializer */
#define PWM_SET_ALIGNED_TYPE(pwm, u32ChannelMask, u32AlignedType) \ do{ \ int i; \ for(i = 0; i < 6; i++) { \ if((u32ChannelMask) & (1 << i)) \ (pwm)->CTL1 = (((pwm)->CTL1 & ~(3UL << ((i >> 1) << 2))) | ((u32AlignedType) << ((i >> 1) << 2))); \ } \ }while(0)02
*************************************************************************************************************************************************************/
/* Clock prescaler 时钟预分频器*/ PWM_SET_PRESCALER(PWM0, 0, 1);//该宏设置所选通道的预分频器
/******************************************************************************************************************************************************** /** * @brief This macro set the prescaler of the selected channel * @param[in] pwm The pointer of the specified PWM module * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 PWM通道 * @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 1 ~ 0xFFF u32Prescaler指定通道的时钟预分频器。
// 有效值在1〜0xFFF之间 * @return None * @details This macro is used to set the prescaler of specified channel. * @note Every even channel N, and channel (N + 1) share a prescaler. So if channel 0 prescaler changed, * channel 1 will also be affected. * \hideinitializer */
#define PWM_SET_PRESCALER(pwm, u32ChannelNum, u32Prescaler) (*(__IO uint32_t *) (&((pwm)->CLKPSC0_1) + ((u32ChannelNum) >> 1)) = (u32Prescaler)) ***********************************************************************************************************************************************************************/
/* PWM counter value */ /* PWM frequency = PWM clock source/(clock prescaler setting + 1)/(CNR+1) */ PWM_SET_CNR(PWM0, 0, 5);//该宏设置所选通道的周期
/**********************************************************************************************************************************************************

/**
* @brief This macro set the period of the selected channel
* @param[in] pwm The pointer of the specified PWM module
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0, 2, 4. Every two channels share the same setting.
* @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF
* @return None
* @details This macro is used to set the period of specified channel.
* @note This new setting will take effect on next PWM period.
* @note PWM counter will stop if period length set to 0.
* \hideinitializer
*/
#define PWM_SET_CNR(pwm, u32ChannelNum, u32CNR) ((pwm)->PERIOD[(((u32ChannelNum) >> 1) << 1)] = (u32CNR))


/** * @brief This macro set the comparator of the selected channel * @param[in] pwm The pointer of the specified PWM module * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 * @param[in] u32CMR Comparator of specified channel. Valid values are between 0~0xFFFF * @return None * @details This macro is used to set the comparator of specified channel. * @note This new setting will take effect on next PWM period. * \hideinitializer */ #define PWM_SET_CMR(pwm, u32ChannelNum, u32CMR) ((pwm)->CMPDAT[(u32ChannelNum)] = (u32CMR))
**********************************************************************************************************************************************************/
/* PWM compare value */ PWM_SET_CMR(PWM0, 0, 1);
/*******************************************************************************************************************************************************
/** * @brief This macro set the comparator of the selected channel 该宏设置所选通道的比较器 * @param[in] pwm The pointer of the specified PWM module * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 * @param[in] u32CMR Comparator of specified channel. Valid values are between 0~0xFFFF 指定通道的u32CMR比较器。 有效值在0〜0xFFFF之间 * @return None * @details This macro is used to set the comparator of specified channel.该宏用于设置指定通道的比较器。 * @note This new setting will take effect on next PWM period.这个新设置将在下一个PWM周期生效。 * \hideinitializer */ #define PWM_SET_CMR(pwm, u32ChannelNum, u32CMR) ((pwm)->CMPDAT[(u32ChannelNum)] = (u32CMR))
***************************************************************************************************************************************************************/ /* Enable PWM0 to trigger ADC */ PWM_EnableADCTrigger(PWM0, 0, PWM_TRIGGER_ADC_EVEN_PERIOD_POINT);//使能PWM来触发ADC
/******************************************************************************************************************************************************
/** * @brief Enable selected channel to trigger ADC * @param[in] pwm The pointer of the specified PWM module * - PWM0 : PWM Group 0 * - PWM1 : PWM Group 1 * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5 * @param[in] u32Condition The condition to trigger ADC. Combination of following conditions: * - \ref PWM_TRIGGER_ADC_EVEN_ZERO_POINT * - \ref PWM_TRIGGER_ADC_EVEN_PERIOD_POINT * - \ref PWM_TRIGGER_ADC_EVEN_ZERO_OR_PERIOD_POINT * - \ref PWM_TRIGGER_ADC_EVEN_COMPARE_UP_COUNT_POINT * - \ref PWM_TRIGGER_ADC_EVEN_COMPARE_DOWN_COUNT_POINT * - \ref PWM_TRIGGER_ADC_ODD_COMPARE_UP_COUNT_POINT * - \ref PWM_TRIGGER_ADC_ODD_COMPARE_DOWN_COUNT_POINT
#define PWM_TRIGGER_ADC_EVEN_ZERO_POINT (0UL)
/*!< PWM trigger ADC while counter of even channel matches zero point */PWM触发ADC,偶数通道计数器匹配零点 #define PWM_TRIGGER_ADC_EVEN_PERIOD_POINT (1UL)
/*!< PWM trigger ADC while counter of even channel matches period point */当偶数通道计数器匹配周期点时,PWM触发ADC #define PWM_TRIGGER_ADC_EVEN_ZERO_OR_PERIOD_POINT (2UL)
/*!< PWM trigger ADC while counter of even channel matches zero or period point */PWM触发ADC,偶数通道计数器匹配零点或周期点 #define PWM_TRIGGER_ADC_EVEN_COMPARE_UP_COUNT_POINT (3UL)
/*!< PWM trigger ADC while counter of even channel matches up count to comparator point */当偶数通道计数器匹配时PWM触发ADC计数到比较器点 #define PWM_TRIGGER_ADC_EVEN_COMPARE_DOWN_COUNT_POINT (4UL)
/*!< PWM trigger ADC while counter of even channel matches down count to comparator point */PWM触发ADC,而偶数通道计数器的匹配下降计数到比较点 #define PWM_TRIGGER_ADC_ODD_COMPARE_UP_COUNT_POINT (8UL)
/*!< PWM trigger ADC while counter of odd channel matches up count to comparator point */PWM触发ADC将奇数通道计数器匹配到比较器点数 #define PWM_TRIGGER_ADC_ODD_COMPARE_DOWN_COUNT_POINT (9UL)
/*!< PWM trigger ADC while counter of odd channel matches down count to comparator point */PWM触发ADC将奇数通道计数器下降计数到比较点 * @return None * @details This function is used to enable selected channel to trigger ADC. */ void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition) { if(u32ChannelNum < 4) { (pwm)->ADCTS0 &= ~((PWM_ADCTS0_TRGSEL0_Msk) << (u32ChannelNum * 8)); (pwm)->ADCTS0 |= ((PWM_ADCTS0_TRGEN0_Msk | u32Condition) << (u32ChannelNum * 8)); } else { (pwm)->ADCTS1 &= ~((PWM_ADCTS1_TRGSEL4_Msk) << ((u32ChannelNum - 4) * 8)); (pwm)->ADCTS1 |= ((PWM_ADCTS1_TRGEN4_Msk | u32Condition) << ((u32ChannelNum - 4) * 8)); } } *************************************************************************************************************************************************************/ /* PWM0 pin output enabled */ PWM_SET_OUTPUT_LEVEL(PWM0, PWM_CH_0_MASK, PWM_OUTPUT_HIGH, PWM_OUTPUT_NOTHING, PWM_OUTPUT_LOW, PWM_OUTPUT_NOTHING);
/*******************************************************************************************************************************************************
/** * @brief Set output level at zero, compare up, period(center) and compare down of specified channel(s)
将输出电平设置为零,比较上升,指定通道的周期(中心)和比较下降 * @param[in] pwm The pointer of the specified PWM module // * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
u32ChannelMask已启用通道的组合。 每一位对应一个通道 * Bit 0 represents channel 0, bit 1 represents channel 1... * @param[in] u32ZeroLevel output level at zero point, valid values are:
u32ZeroLevel输出电平在零点,有效值是: * - \ref PWM_OUTPUT_NOTHING * - \ref PWM_OUTPUT_LOW * - \ref PWM_OUTPUT_HIGH * - \ref PWM_OUTPUT_TOGGLE * @param[in] u32CmpUpLevel output level at compare up point, valid values are:
u32CmpUpLevel比较点的输出电平,有效值为: * - \ref PWM_OUTPUT_NOTHING * - \ref PWM_OUTPUT_LOW * - \ref PWM_OUTPUT_HIGH * - \ref PWM_OUTPUT_TOGGLE * @param[in] u32PeriodLevel output level at period(center) point, valid values are:
周期(中心)点的u32PeriodLevel输出电平,有效值为: * - \ref PWM_OUTPUT_NOTHING * - \ref PWM_OUTPUT_LOW * - \ref PWM_OUTPUT_HIGH * - \ref PWM_OUTPUT_TOGGLE * @param[in] u32CmpDownLevel output level at compare down point, valid values are:
@param [in] u32CmpDownLevel比较下来的输出级别,有效值是: * - \ref PWM_OUTPUT_NOTHING * - \ref PWM_OUTPUT_LOW * - \ref PWM_OUTPUT_HIGH * - \ref PWM_OUTPUT_TOGGLE * @return None * @details This macro is used to Set output level at zero, compare up, period(center) and compare down of specified channel(s). * \hideinitializer */ #define PWM_SET_OUTPUT_LEVEL(pwm, u32ChannelMask, u32ZeroLevel, u32CmpUpLevel, u32PeriodLevel, u32CmpDownLevel) \ do{ \ int i; \ for(i = 0; i < 6; i++) { \ if((u32ChannelMask) & (1 << i)) { \ (pwm)->WGCTL0 = (((pwm)->WGCTL0 & ~(3UL << (2 * i))) | ((u32ZeroLevel) << (2 * i))); \ (pwm)->WGCTL0 = (((pwm)->WGCTL0 & ~(3UL << (PWM_WGCTL0_PRDPCTLn_Pos + (2 * i)))) | \
((u32PeriodLevel) << (PWM_WGCTL0_PRDPCTLn_Pos + (2 * i)))); \ (pwm)->WGCTL1 = (((pwm)->WGCTL1 & ~(3UL << (2 * i))) | ((u32CmpUpLevel) << (2 * i))); \ (pwm)->WGCTL1 = (((pwm)->WGCTL1 & ~(3UL << (PWM_WGCTL1_CMPDCTLn_Pos + (2 * i)))) | \
((u32CmpDownLevel) << (PWM_WGCTL1_CMPDCTLn_Pos + (2 * i)))); \ } \ } \ }while(0) **********************************************************************************************************************************************************************************************************/ PWM_EnableOutput(PWM0, PWM_CH_0_MASK);
/*****************************************************************************************************************************************************
/* Start PWM module */ PWM_Start(PWM0, PWM_CH_0_MASK); /* wait for one cycle */ while(PWM_GetPeriodIntFlag(PWM0, 0) == 0); while(PWM_GetZeroIntFlag(PWM0, 0) == 0); PWM_ClearPeriodIntFlag(PWM0, 0); PWM_ClearZeroIntFlag(PWM0, 0); /********************************************************************************************************************************************************
/** * @brief Get period interrupt of selected channel 获取选定通道的周期中断 * @param[in] pwm The pointer of the specified PWM module * - PWM0 : PWM Group 0 * - PWM1 : PWM Group 1 * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. * @return Period interrupt flag of specified channel * @retval 0 Period interrupt did not occur * @retval 1 Period interrupt occurred * @details This function is used to get period interrupt of selected channel. */ uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) { return (((pwm)->INTSTS0 & (PWM_INTSTS0_PIF0_Msk << ((u32ChannelNum >> 1) << 1))) ? 1 : 0); }
/** * @brief Get zero interrupt of selected channel 获取所选通道的零中断 * @param[in] pwm The pointer of the specified PWM module * - PWM0 : PWM Group 0 * - PWM1 : PWM Group 1 * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5. Every two channels share the same setting. * @return zero interrupt flag of specified channel * @retval 0 zero interrupt did not occur * @retval 1 zero interrupt occurred * @details This function is used to get zero interrupt of selected channel. */ uint32_t PWM_GetZeroIntFlag(PWM_T *pwm, uint32_t u32ChannelNum) { return (((pwm)->INTSTS0 & (PWM_INTSTS0_ZIF0_Msk << ((u32ChannelNum >> 1) << 1))) ? 1 : 0); }
/** * @brief Stop PWM generation immediately by clear channel enable bit * @param[in] pwm The pointer of the specified PWM module * - PWM0 : PWM Group 0 * - PWM1 : PWM Group 1 * @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel. * Bit 0 is channel 0, bit 1 is channel 1... * @return None * @details This function is used to stop PWM generation immediately by clear channel enable bit. 该功能用于通过清除通道使能位立即停止PWM的产生。 */ void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask) { uint32_t i; for(i = 0; i < PWM_CHANNEL_NUM; i ++) { if(u32ChannelMask & (1 << i)) { (pwm)->CNTEN &= ~(1UL << ((i >> 1) << 1)); } } }
/** * @brief Return the user-specified interrupt flags. 返回用户指定的中断标志。 * @param[in] adc The pointer of the specified ADC module. * @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status.//u32Mask以下中断状态位的组合。 每个位对应一个中断状态 * Valid values are: * - \ref ADC_ADF_INT :Convert complete interrupt flag. * - \ref ADC_CMP0_INT :Comparator 0 interrupt flag. * - \ref ADC_CMP1_INT :Comparator 1 interrupt flag. * @return User specified interrupt flags. * @details Get the status of the ADC interrupt flag. */ #define ADC_GET_INT_FLAG(adc, u32Mask) ((adc)->ADSR & (u32Mask))
**************************************************************************************************************************************************************/ /* Stop PWM generation */ PWM_ForceStop(PWM0, PWM_CH_0_MASK); /* Wait conversion done */ while(!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT)); /* Clear the ADC interrupt flag */ ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT); printf("Channel 2: 0x%X\n", ADC_GET_CONVERSION_DATA(ADC, 2));//ADC获取转换数据 /* Disable ADC */ ADC_POWER_DOWN(ADC);
/*********************************************************************************************************************************************************
///**    *提示关闭ADC模块。    * @param [in] adc指定ADC模块的指针。    * @返回无    * @details禁用A / D转换器模拟电路以节省功耗。    * @note无   */
#define ADC_POWER_DOWN(adc)((adc) - > ADCR&=〜ADC_ADCR_ADEN_Msk)
 
  
***********************************************************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------*/ 
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(
void) { /* Unlock protected registers */
SYS_UnlockReg();
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init UART0 for printf */
UART0_Init();
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
printf(
"\nSystem clock rate: %d Hz", SystemCoreClock);
/* ADC hardware trigger test */
ADC_PWMTrigTest_SingleOpMode();
/* Disable ADC module */
ADC_Close(ADC);
/* Disable ADC IP clock */
CLK_DisableModuleClock(ADC_MODULE);
/* Disable External Interrupt */
NVIC_DisableIRQ(ADC_IRQn);
printf(
"\nExit ADC sample code\n");
while(1);
}

这里插几则知识点:
1. 边沿对齐模式
   当PWM 时基工作在自由运行模式时,模块产生边沿对齐的PWM 信号。给定PWM 通道的输出
信号的周期由装入PTPER 的值指定, 其占空比由相应的PDCx 寄存器指定(参见图15-7 )。
设占空比非零且立即更新未被使能( IUE = 0),所有使能的PWM 发生器的输出在PWM 周期开
始( PTMR = 0)时被驱动为有效。当PTMR 的值与PWM 发生器的占空比值发生匹配时,各
PWM 输出都被驱动为无效。
如果PDCx 寄存器中的值为0,则相应的PWM 引脚的输出在整个PWM 周期内都将为无效。此
外,如果PDCx 寄存器中的值大于PTPER 寄存器中保存的值, 那么PWM 引脚的输出在整个
PWM 周期内都将有效。
如果使能了立即更新( IUE = 1),则在新值写入任一有效的PDC 寄存器时,新的占空比值即被
装入。
PWM模块:边沿对齐PWM和中心对齐PWM

2. 边沿对齐模式
    当PWM时基配置为两个向上/向下计数模式(PTMOD<1:0> = 1x)之一时,模块将产生中心对齐的PWM信号。
当占空比寄存器的值与PTMR的值相匹配,并且PWM时基正在向下计数(PTDIR = 1)时,
 
PWM比较输出驱动为有效状态。当PWM时基正在向上计数(PTDIR = 0),且PTMR寄存器中的值与占空比值匹配时,PWM比较输出将驱动为无效状态。
如果特定占空比寄存器中的值为0,则相应PWM引
 
脚的输出在整个PWM周期中都将为无效。此外,如果占空比寄存器中的值大于PTPER寄存器中保存的值,则PWM引脚的输出在整个PWM周期内都将有效.
PWM模块:边沿对齐PWM和中心对齐PWM

 看了这么多,有些乱了吧,不要着急,后面是对这个程序的详细说明,做技术要有耐心,细心

这个程序是说,选定PWM如何触发ADC的取值,在示波器上观察波形,在串口上观察ADC读取的数据, PWM选取了通道0,ADC选取了通道2,也就是说ADC通道2读取到的数值,通过PWM0触发了ADC的取值。

void ADC_PWMTrigTest_SingleOpMode()
{
    printf("\n<<< PWM trigger test (Single mode) >>>\n");

    /* Set the ADC operation mode as single, input mode as single-end and enable the analog input channel 2 */
    ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, 0x1 << 2);//操作模式选为单段输入模式,输入模式位单一模式

    /* Power on ADC module */
    ADC_POWER_ON(ADC);

    /* Configure the hardware trigger condition and enable hardware trigger; PWM trigger delay: (4*10) system clock cycles*/
    ADC_EnableHWTrigger(ADC, ADC_ADCR_TRGS_PWM, 0);//硬件触发条件

    /* Clear the A/D interrupt flag for safe */
    ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

    /* Center-aligned type */
    PWM_SET_ALIGNED_TYPE(PWM0, PWM_CH_4_MASK, PWM_CENTER_ALIGNED);
    /* Clock prescaler */
    PWM_SET_PRESCALER(PWM0, 0, 1);
    /* PWM counter value */ /* PWM frequency = PWM clock source/(clock prescaler setting + 1)/(CNR+1) */
    PWM_SET_CNR(PWM0, 0, 5);
    /* PWM compare value */
    PWM_SET_CMR(PWM0, 0, 1);
    /* Enable PWM0 to trigger ADC */
    PWM_EnableADCTrigger(PWM0, 0, PWM_TRIGGER_ADC_EVEN_PERIOD_POINT);
    /* PWM0 pin output enabled */
    PWM_SET_OUTPUT_LEVEL(PWM0, PWM_CH_0_MASK, PWM_OUTPUT_HIGH, PWM_OUTPUT_NOTHING, PWM_OUTPUT_LOW, PWM_OUTPUT_NOTHING);

    PWM_EnableOutput(PWM0, PWM_CH_0_MASK);

    /* Start PWM module */
    PWM_Start(PWM0, PWM_CH_0_MASK);

    /* wait for one cycle */
    while(PWM_GetPeriodIntFlag(PWM0, 0) == 0);
    while(PWM_GetZeroIntFlag(PWM0, 0) == 0);
    PWM_ClearPeriodIntFlag(PWM0, 0);
    PWM_ClearZeroIntFlag(PWM0, 0);

    /* Stop PWM generation */
    PWM_ForceStop(PWM0, PWM_CH_0_MASK);

    /* Wait conversion done */
    while(!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT));

    /* Clear the ADC interrupt flag */
    ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

    printf("Channel 2: 0x%X\n", ADC_GET_CONVERSION_DATA(ADC, 2));

    /* Disable ADC */
    ADC_POWER_DOWN(ADC);

    while(1);
}

PWM0通道发出波形,ADC2通道读取数值。

A/D转换器支持三种操作模式:单一(single),单周期扫描(single-cycle scan)和连续扫描模式(continuous scan mode)。A/D转换器可由软件、PWM、BPWM触发器和外部STADC管脚启动转换。

输入模式分为单端输入和差分输入模式。

 

差分输入方式:差分输入的是将两个输入端的差值作为信号,这样可以免去一些误差,比如输入一个1V的信号电源有偏差,比实际输入要大0.1.就可以用差分输入1V和2V,一减就把两端共有的那0.1误差剪掉了。单端输入无法去除这类误差。
一个差分信号是用一个数值来表示两个物理量之间的差异。从严格意义上来讲,所有电压信号都是差分的,因为一个电压只能是相对于另一个电压而言的。
在某些系统里,系统'地'被用作电压基准点。当'地'当作电压测量基准时,这种信号规划被称之为单端的。使用该术语是因为信号是用单个导体上的电压来表示的。
另一方面,一个差分信号作用在两个导体上。信号值是两个导体间的电压差。尽管不是非常必要,这两个电压的平均值还是会经常保持一致。

这里有一个网友问的关于TI的一个关于ADC的问题,或许有助于了解一下ADC的输入模式(单端或差分):
硬件触发源
1.外部STADC引脚启动
2.由PWM启动
 硬件触发条件分为
1.ADC_ADCR_TRGCOND_LOW_LEVEL 
2.ADC_ADCR_TRGCOND_HIGH_LEVEL
3.ADC_ADCR_TRGCOND_FALLING_EDGE
4.ADC_ADCR_TRGCOND_RISING_EDGE

PWM_SET_OUTPUT_LEVEL函数的四个参数:
1.输出电平在零点
2.比较点的输出电平,
 
3.周期(中心)点的输出电平,
4.比较下来的输出级别,




关于零点事件与周期时间,你是否明白了?还有就是比较器事件


 

 
采样一个信号,以前直接放大送给ADC。TI很多ADC(只关注16bit的系列)的模拟信号输入端都是AINP/AINN,即支持差分输入。我的问题是:

             1:这个差分输入和和单端输入在本质 上到底有什么区别? 因为,ADC采集的信号说到底是AINP - AINN,不管单端还是差分,采集的信号都是这两个pad的差值。

    差分信号是 AINP - AINN

              单端信号是 AIN - REFN

            2:将单端信号接在ADC的差分输入接口上可以用吗?可以

           

            3:如果将差分放大器输出的差分信号,接在只支持单端信号输入的ADC,会正常工作吗?不会,结果会出现错误

 

PWM中断触发ADC采样和ADC中断是一个东西吗?


首先要区分adc在这里扮演的角色,pwm中断出发adc采样是去读取某个参数,而adc中断是在某个参数达到一定限制时发出一个中断。性质不一样的哩。

PWM触发ADC启动转换有什么用

 典型应用是电机控制里面的相电流控制,pwm打开之后ADC对相电流同步采样,然后做电流PID反馈环

简单地说,补码就是反码加1。
计算机中为什么要使用补码呢?
主要原因:1、使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补 码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
2、补码与原码的转换过程几乎是相同的。
(1)正数的补码
  与原码相同。   【例1】+9的补码是00001001。(备注:这个+9的补码说的是用8位的2进制来表示补码的,补码表示方式很多,还有16位2进制补码表示形式,以及32位2进制补码表示形式等。)
(2)负数的补码
  符号位为1,其余位为该数绝对值的原码按位取反;然后整个数加1。   同一个数字在不同的补码表示形式里头,是不同的。比方说-15的补码,在8位2进制里头是11110001,然而在16位2进制补码表示的情况下,就成了1111111111110001。在这篇补码概述里头涉及的补码转换默认了把一个数转换成8位2进制的补码形式,每一种补码表示形式都只能表示有限的数字。   【例2】求-7的补码。
  因为给定数是负数,则符号位为“1”。
  后七位:+7的原码(0000111)→按位取反(1111000)→加1(1111001)
  所以-7的补码是11111001。
  已知一个数的补码,求原码的操作分两种情况:
  (1)如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
  (2)如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。
  另一种方法求负数的补码如下:
  例如:求-15的补码
  第一步:+15:00001111
  第二步:逐位取反(1变成0,0变成1),然后在末尾加1。
  11110001
  再举一个例子验证下:求-64的补码
  +64:01000000
  11000000
  【例3】已知一个补码为11111001,则原码是10000111(-7)。
  因为符号位为“1”,表示是一个负数,所以该位不变,仍为“1”。
  其余七位1111001取反后为0000110;
  再加1,所以是10000111。

转载于:https://www.cnblogs.com/zhugeanran/p/8400711.html

<think>我们正在讨论显示面板技术中的两个术语:HXT和MLHXT。根据用户提供的引用,HXT出现在两个上下文中:1.在引用[1]中,HXT-PMS70E是一种触摸屏监控设备,与显示面板的监控相关。2.在引用[2]中,HXT6112是一种激光器驱动芯片(用于光纤通信),与显示面板技术没有直接关系。但是,用户的问题明确指向显示面板技术,并且要求参考上一次的对话(即关于横向串扰和data线跳变的讨论)。因此,我们需要将HXT和MLHXT放在显示面板技术的背景下理解。在显示面板领域,HXT通常指“横向串扰”(HorizontalCross-Talk),而MLHXT可能是“多线横向串扰”(Multi-LineHorizontalCross-Talk)或类似术语。然而,MLHXT并不是一个标准术语,我们需要根据上下文推断。回顾上一次对话,我们详细讨论了横向串扰(HXT)和data线跳变引起的亮度变化。因此,用户可能是在询问横向串扰(HXT)与另一种串扰(MLHXT)的区别。在显示技术中,常见的串扰分类包括:-横向串扰(HorizontalCross-Talk,HXT):由相邻数据线之间的电容耦合引起,表现为水平方向上的亮度不均。-纵向串扰(VerticalCross-Talk):由扫描线(Gate线)的耦合引起,表现为垂直方向上的亮度不均。-多线串扰(Multi-LineCross-Talk):可能指涉及多条线路(如多条数据线或扫描线)的串扰,影响范围更广。因此,我推测MLHXT可能是指“多线横向串扰”(Multi-LineHorizontalCross-Talk),即同时影响多条水平线路的串扰现象。下面将详细解释两者的区别。###HXT(横向串扰)与MLHXT(多线横向串扰)在显示面板技术中的区别####1.**定义与基本机制**-**HXT(横向串扰)**:指单条数据线(DataLine)的信号变化通过电容耦合影响其相邻的一条或两条数据线,导致相邻像素的亮度发生变化。这种串扰通常局限于直接相邻的像素,影响范围较小。其物理机制主要是相邻线路之间的寄生电容$C_c$[^1]。-**MLHXT(多线横向串扰)**:指多条数据线同时发生信号变化时,产生的耦合效应叠加,影响范围扩展到多条线路(如3条以上)甚至整个面板区域。这种串扰通常由信号同步跳变(如全屏画面切换)引起,其耦合机制包括:-多线路间的分布式电容耦合-电源噪声的放大效应(因多条线路同时切换导致电流突变)####2.**影响范围与表现形式**-**HXT**:影响范围小,表现为局部亮度不均(如相邻像素的亮带或暗带)。例如,在显示垂直条纹图案时,相邻条纹边缘可能出现亮度渗透[^1]。-**MLHXT**:影响范围大,可能表现为大面积亮度波动或闪烁。例如,当整个屏幕从黑色切换到白色时,多条数据线同时跳变,导致屏幕中间区域出现短暂亮度不均[^1]。####3.**数学模型的差异**-**HXT的耦合模型**:通常用相邻两条数据线之间的电容耦合电压描述:$$\DeltaV_{\text{adjacent}}=C_c\cdot\frac{dV_{\text{active}}}{dt}\cdotR_{\text{load}}$$其中$V_{\text{active}}$是活跃数据线的电压变化率,$R_{\text{load}}$是像素负载电阻。-**MLHXT的耦合模型**:需考虑多条线路的耦合叠加效应。假设$N$条数据线同步跳变,耦合到目标线路的噪声电压为:$$\DeltaV_{\text{multi}}=\sum_{i=1}^{N}C_{c_i}\cdot\frac{dV_i}{dt}\cdotR_{\text{load}}$$其中$C_{c_i}$是第$i$条线路与目标线路的耦合电容。当多条线路$\frac{dV_i}{dt}$相位一致时,噪声会显著放大。####4.**触发条件与测试方法**-**HXT**:在静态图像或低频刷新下测试(如显示棋盘格图案)。-**MLHXT**:在高动态画面(如全屏快速切换)或高频刷新率下测试(如120Hz视频)。####5.**解决方案的差异**-**HXT缓解**:-优化数据线布局(如增加线间距)-加入屏蔽线(ShieldingLines)-使用补偿算法(在驱动IC中调整相邻像素电压)[^1]-**MLHXT缓解**:-改进电源完整性(如增加去耦电容)-数据线分组驱动(避免多条线路同步切换)-采用时序偏移技术(StaggeredDriving),使多条数据线的跳变时间错开[^1]####6.**实际案例对比**-**HXT案例**:在LCD面板中,显示单像素宽度的垂直线条时,线条边缘出现模糊。-**MLHXT案例**:在OLED面板播放高速运动画面时,场景切换导致屏幕短暂出现波浪状亮度波纹。###总结|特性|HXT(横向串扰)|MLHXT(多线横向串扰)||--------------|-------------------------------------|-------------------------------------||**影响范围**|局部(1-2条相邻数据线)|全局(多条数据线或整屏)||**主要成因**|单条数据线跳变的电容耦合|多条数据线同步跳变的耦合叠加||**表现形式**|静态边缘亮度渗透|动态大面积亮度波动||**关键参数**|寄生电容$C_c$|同步跳变线路数$N$和电源噪声||**解决方案**|布局优化、屏蔽线|电源改进、时序偏移驱动|在显示面板设计中,两者都需针对性处理以确保画质。HXT更常见于高分辨率面板,而MLHXT在高刷新率面板(如游戏显示器)中更显著[^1]。§§相关问题§§1.如何通过驱动电路设计减少MLHXT?2.在柔性OLED面板中,HXT和MLHXT有什么特殊表现?3.有哪些标准测试图案用于量化HXT和MLHXT?4.电源噪声对MLHXT的影响机制是什么?[^1]:显示面板设计中的信号完整性与耦合效应分析。</think>### HXT 与 MLHXT 在显示面板技术中的区别 在显示面板技术领域,**HXT**(Horizontal Cross-Talk,横向串扰)和 **MLHXT**(Multi-Line Horizontal Cross-Talk,多线横向串扰)是两种不同层级的信号干扰现象,核心区别在于**影响范围、耦合机制和表现形式**。以下是基于显示面板工作原理的详细对比分析: --- #### 1. **定义与物理机制** - **HXT(横向串扰)** 指单条数据线(Data Line)的信号变化通过**寄生电容耦合**影响其**直接相邻**的数据线或像素电路,导致局部亮度不均。 **数学描述**: 若数据线$i$的电压变化率为$\frac{dV_i}{dt}$,相邻数据线$j$的耦合噪声电压为: $$\Delta V_j = C_{c} \cdot R_{\text{load}} \cdot \frac{dV_i}{dt}$$ 其中$C_c$是线间寄生电容,$R_{\text{load}}$是负载电阻[^1]。 **影响范围**:仅限直接相邻的1-2条数据线。 - **MLHXT(多线横向串扰)** 指**多条数据线同步跳变**时,通过**分布式电容耦合和电源噪声**产生的叠加干扰,影响范围扩展到**多条非相邻线路或整块区域**。 **数学描述**: 当$N$条数据线同步跳变时,目标线路$k$的噪声电压为: $$\Delta V_k = \sum_{i=1}^{N} C_{c_i} \cdot \frac{dV_i}{dt} \cdot R_{\text{load}} + \Delta V_{\text{power}}$$ 其中$\Delta V_{\text{power}}$是电源波动贡献的噪声[^1]。 **影响范围**:3条以上数据线或局部面板区域。 --- #### 2. **表现形式对比** | **特征** | **HXT** | **MLHXT** | |----------------|------------------------------------|------------------------------------| | **空间表现** | 局部亮/暗条纹(如相邻像素边缘模糊) | 大面积亮度波动(如波浪状亮度不均) | | **时间表现** | 静态图像中显著 | 动态画面切换时更明显 | | **典型场景** | 高分辨率面板的静态灰度显示 | 高刷新率面板(120Hz+)的全屏切换 | | **测试图案** | 单像素垂直线条 | 全屏黑白切换或快速滚动图案 | --- #### 3. **根本原因差异** - **HXT 主导因素**: 由**线路间寄生电容**($C_c$)主导,与数据线物理间距成反比。在LCD中表现为相邻像素电压偏移,在OLED中影响驱动晶体管$V_g$[^1]。 - **MLHXT 主导因素**: 是**多线路同步跳变 + 电源完整性**问题: - 多条Data线$\frac{dV}{dt}$叠加放大耦合噪声 - 同步跳变导致电源瞬时跌落($\Delta V_{\text{power}}$) - 面板边缘效应(如扫描线延迟)加剧干扰 --- #### 4. **解决方案对比** | **方法** | **针对 HXT** | **针对 MLHXT** | |------------------------|---------------------------------------|-------------------------------------| | **布局优化** | 增加数据线间距/加入屏蔽线 | 数据线分组布局,避免并行长走线 | | **驱动技术** | 电压补偿算法(调整相邻像素电压) | 时序偏移驱动(Staggered Driving) | | **电路设计** | 减小寄生电容$C_c$ | 增强电源去耦电容 + 低阻抗电源网络 | | **面板技术适配** | LCD中更显著,需优化ITO电极 | OLED中更严重,需优化TFT背板设计 | --- #### 5. **实际案例说明** - **HXT 案例**: 在4K LCD面板显示棋盘格时,黑白格交界处出现**1-2像素宽的亮度渗透**,因高密度布线导致$C_c$增大[^1]。 - **MLHXT 案例**: 在OLED游戏显示器(144Hz)快速切换暗场→亮场时,屏幕中部出现**横向亮度波纹**,因数百条Data线同步跳变引发电源噪声共振[^1]。 --- ### 总结 | **维度** | **HXT** | **MLHXT** | |--------------|----------------------------------|----------------------------------| | **本质** | 单点电容耦合 | 多点耦合+电源噪声叠加 | | **范围** | 微观(相邻线路) | 宏观(区域/全局) | | **关键参数** | 寄生电容$C_c$ | 同步跳变线路数$N$ + 电源阻抗$Z$ | | **设计重心** | 局部布线优化 | 系统级信号/电源完整性 | > 简言之:**HXT是“邻居干扰邻居”,MLHXT是“群体干扰群体+电源失控”**。两者需在面板设计的不同层级解决——HXT依赖物理布局优化,MLHXT需系统级驱动策略和电源设计[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值