今天我来讲讲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());//分频 /* 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()); /* Select PWM01 module clock source */
CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL3_PWM0_S_PCLK, ); /* 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()); /*---------------------------------------------------------------------------------------------------------*/
/* 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, );
} /*---------------------------------------------------------------------------------------------------------*/
/* 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 << );
//将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, );//配置硬件触发条件并启用硬件触发; 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, , );//该宏设置所选通道的预分频器
/********************************************************************************************************************************************************
/**
* @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, , );//该宏设置所选通道的周期
/**********************************************************************************************************************************************************

/**
* @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, , );
/*******************************************************************************************************************************************************

/**
* @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, , 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, ) == );
while(PWM_GetZeroIntFlag(PWM0, ) == );
PWM_ClearPeriodIntFlag(PWM0, );
PWM_ClearZeroIntFlag(PWM0, );
/********************************************************************************************************************************************************
/**
* @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, ));//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. 边沿对齐模式
   当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 寄存器时,新的占空比值即被
装入。

2. 边沿对齐模式
    当PWM时基配置为两个向上/向下计数模式(PTMOD<1:0> = 1x)之一时,模块将产生中心对齐的PWM信号。

当占空比寄存器的值与PTMR的值相匹配,并且PWM时基正在向下计数(PTDIR = 1)时,
 
PWM比较输出驱动为有效状态。当PWM时基正在向上计数(PTDIR = 0),且PTMR寄存器中的值与占空比值匹配时,PWM比较输出将驱动为无效状态。
如果特定占空比寄存器中的值为0,则相应PWM引
 
脚的输出在整个PWM周期中都将为无效。此外,如果占空比寄存器中的值大于PTPER寄存器中保存的值,则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 << );//操作模式选为单段输入模式,输入模式位单一模式 /* 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, );//硬件触发条件 /* 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, , );
/* PWM counter value */ /* PWM frequency = PWM clock source/(clock prescaler setting + 1)/(CNR+1) */
PWM_SET_CNR(PWM0, , );
/* PWM compare value */
PWM_SET_CMR(PWM0, , );
/* Enable PWM0 to trigger ADC */
PWM_EnableADCTrigger(PWM0, , 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, ) == );
while(PWM_GetZeroIntFlag(PWM0, ) == );
PWM_ClearPeriodIntFlag(PWM0, );
PWM_ClearZeroIntFlag(PWM0, ); /* 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, )); /* Disable ADC */
ADC_POWER_DOWN(ADC); while();
}

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。

NUC131演示如何通过PWM触发ADC。的更多相关文章

  1. RTT学习之PWM、ADC设备

    一 使用步骤: 查找 PWM 设备获取设备句柄.rt_device_find() 设置 PWM 周期和脉冲宽度.rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, ...

  2. STM32定时器触发ADC多通道连续采样,DMA缓存结果

    STM32的ADC使用非常灵活,采样触发方面:既支持软件触发,定时器或其他硬件电路自动触发,也支持转换完成后自动触发下一通道/轮转换.转换结果存储方面:既支持软件读取和转存,也支持DMA自动存储转换结 ...

  3. PWM实现ADC和DAC

    一.PWM实现AD 利用普通单片机的2个IO及一个运算放大器即可实现AD转换电路,而且很容易扩展成多通道.其占用资源少,成本低,AD 转换精度可以达到8位甚至更高,因此具有一定的实用价值. 1.1 硬 ...

  4. BLDC有感FOC算法理论及其STM32软硬件实现

    位置传感器:旋转编码器          MCU:STM32F405RGT6          功率MOS驱动芯片:DRV8301 全文均假设在无弱磁控制的情况下 FOC算法理论 首先,我们要知道FO ...

  5. ADC配置成定时器触发的启发

    百度文库:https://wenku.baidu.com/view/99d39413f78a6529647d5344.html STM32关于使用定时器触发ADC转换的解决办法和详细说明 本人在使用S ...

  6. STM32F103ZET6 之 ADC+TIM+DMA+USART 综合实验

    1.实验目的 1)使用 TIM1 触发 ADC,ADC 采集的数据通过DMA 传至内存,然后通过串口打印出采集的数据: 2)学会 DMA 传输数据并将数据进行保存: 3)验证ADC 的采样率与实际设置 ...

  7. 四轴遥控器ADC部分

    一.ADC参考手册学习 A/D转换可以按单次.连续设置采样:可以一一扫描或间断的对多个ADC通道进行采集. ADC的结果有左对齐和右对齐. ADC的输入时钟不得超过14Mhz,它是由PCLK2经分频产 ...

  8. WS2812B彩灯详细讲解篇(STM32 PWM+DMA控制 STM32 HAL库编程 循环延时控制多种控制方式)

    一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1JT4y1P72Q 二. 基础认识 (一)  小理论 WS2812B是一种智能控制LED光源,将控制电路 ...

  9. 用STM32内置的高速ADC实现简易示波器

    做一个数字采样示波器一直是我长久以来的愿望,不过毕竟这个目标难度比较大,涉及的方面实在太多,模拟前端电路.高速ADC.单片机.CPLD/FPGA.通讯.上位机程序.数据处理等等,不是一下子就能成的,慢 ...

随机推荐

  1. 【iOS】TableView的footerView不随cell滚动而停留在tableView底部的问题

    苹果官方给我提供TableView的FooterView和HeaderView停留在顶部的非常不错效果,有时候我们不须要这些FooterView和HeaderView停留在底部或者上部,如今就以Foo ...

  2. Android——数据存储:手机外部存储 SD卡存储

    xml <EditText android:layout_width="match_parent" android:layout_height="wrap_cont ...

  3. LUA中获得服务器IP

    local t = {} -- 引入相关包local socket = require("socket") function t.main() local a,b=pcall(t. ...

  4. Yii CDbCriteria 常用方法

    一.一个sql拼装的情况 $criteria = new CDbCriteria; //函数方式 $criteria->addCondition("id=1"); //查询条 ...

  5. ScriptX使用

    自己研究了一下ScriptX并且做了个事例,希望可以帮到需要的同学 下载地址: http://download.csdn.net/detail/jine515073/7234575

  6. 用户数据验证的正确姿势之assert

    用户数据验证灰常重要, 不用多说了, 但是实现方法(准确的说是表现形式)有很多人, 如何优雅的完成一个后端验证过滤器是一个值得考量的问题, 我尝试过许多方法, 比如validator.js模块, ex ...

  7. GDI+(一):GDI+ 绘图基础

    一.GDI+绘图基础 编写图形程序时需要使用GDI(Graphics Device Interface,图形设备接口),从程序设计的角度看,GDI包括两部分:一部分是GDI对象,另一部分是GDI函数. ...

  8. mysql 修改用户权限,允许远程连接数据库

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'admin123' WITH GRANT OPTION; flush privileg ...

  9. Mastering the game of Go with deep neural networks and tree search浅析

    Silver, David, et al. "Mastering the game of Go with deep neural networks and tree search." ...

  10. try catch 异常处理

    1.捕获指定异常 2.捕获所有异常(catch(...))