This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP432P401R:初始化ADC MSP432,健全性检查

Guru**** 2611705 points
Other Parts Discussed in Thread: MSP432WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/662092/msp432p401r-initialize-adc-msp432-sanity-check

部件号:MSP432P401R
主题中讨论的其他部件:MSP432WARE

大家好,

我正在寻找MSP432 ADC设置的健全性检查。 如果有人能确认以下所有内容是否正确(没有任何明显的错误会导致ADC读数混乱),我将非常感激。  我在程序开始时调用initialize_adcs()函数一次,优先处理 ADC14_IRQHandler() ISR,如下所示。

MAP_InterrupT_setPriority (FAULT_Systick,0x10);
MAP_Interrupt_setPriority (INT_Port1,0x20);
MAP_Interrupt_setPriority (INT_ADC14,0x20); 

然后,在主while ()循环之前,我调用一次以下命令:

		ADC14->CTL0 |= ADC14_CTL0_ENC |/*!<		ADC14启用转换-与MAP_ADC14_ToggleConversionTrigger()相同;*/
				ADC14_CTL0_SC;					/*!< ADC14开始转换*/ 

我正在读取ADC 0-13并拉出内部温度传感器信息,需要进行一些不明确的修改... (这是我关注以下设置的主要原因)

void initialize_adics(void)
{

//初始化共享参考模块。 默认情况下,REFMMSTR=1 => REFCTL用于配置内部引用
while (REF_A->CTL0 & REF_A_CTL0_GENBUSY);//如果ref发生器忙,请等待

ref_A->CTL0 || REF_A_CTL0_VSEL_0 | //启用内部1.2V参考
ref_a_CTL0_On; //打开参考
ref_A->CTL0 || REF_A_CTL0_ON; //打开参考
ref_A->CTL0 &=~REF_A_CTL0_TCOFF; //启用温度传感器

	//打开ADC14,延长采样时间以避免结果溢出
	ADC14->CTL0 = ADC14_CTL0_ON |		/*!< ADC14 ON */
			ADC14_CTL0_MSC |			/*!< ADC14多个采样和转换*/
			ADC14_CTL0_SHT0_SE14_SE14*		
						和SE192_ PUL192_
					选择通道

ADC14->CTL1 || ADC14_CTL1_TCMAP; //启用内部温度传感器

	ADC14->MCTL[0]= ADC14_MCTLN_INICT_0;// ref+=AVcc, channel = A0
	ADC14->MCTL[1]= ADC14_MCTLN_INIC;// ref+=AVCC, channel = A1
	ADC14->MCTL14; AVCC_CAF_CAF_A14_CAF_CAX_CAX14
		
		
	// ADC输入通道A22 =>温度感应
//	ADC14->MCTL[5]= ADC14_MCTLN_Inch_5;	//原始代码,不带温度传感器
	ADC14->MCTL[6]= ADC14_MCTLN_Inch_6;	// ref+=AVCC,通道= A6 ADC14->MCTL14
	inch_CC_FC14;	
		通道=8 inch_MCTL14_CAF_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX_CAX
		// ref+=AVcc,channel = A9
	ADC14->MCTL[10]= ADC14_MCTLN_INICT_10;	// ref+=AVcc,channel = A10
	ADC14->MCTL[11]= ADC14_MCTLN_INICT_11;	// ref+=TLcc,channel = A11 ADC14->MCTL14
		;AVCC_13 EOS_ADC14=
	13 inch_13
			

	//启用ADC14IFG.7

	while (!(REF_A->CTL0 & REF_A_CTL0_GENRDY);	//等待参考生成器稳定

	__ENable_interrupT();
	NVIC->ISER[0]= 1 <<(ADC14_IRQn)和31);//启用ADCA0_GRIF14_CAMPL14_





	
	
		
		
		A0results[1]= ADC14->MEM[1];
		A0results[2]= ADC14->MEM[2];
		A0results[3]= ADC14->MEM[3];
		y2_sim = A0results[3];
		A0results[4]= ADC14->MEM[4];
		A0results[5]= ADC14->MEM[5];
		temp = A0results[5];
		Life_off1[0]= ADC14->MEM[6];
		Lift_off1[1]= ADC14->MEM[7];
		Lift_off1[2]= ADC14->MEM[8];
		Lift_off2[0]= ADC14->MEM[9];
		Lift_off2[1]= ADC14->MEM[10];Lift_off2[1]= ADC14->MEM[10];
		Lift_off2[2]= ADC11_EM[14]
		A0results[12]= ADC14->MEM[12];
		A0results[13]= ADC14->MEM[13];
	}

我最担心的是ADC值无故跳转会在我们的系统中触发不必要的影响。

谢谢!

Bob

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Bob,您好!

    SimpleLink SDK正尝试从注册操作移动到API操作的更多操作。 例如,请参阅下的SDK示例

    C:\ti\simplelink_msp432p4_sdk_1_60_00_12\examples\nortos\MSP_EXP432P401R\driverlib

    使用API可以帮助我们重现问题,同时也可以帮助您避免初始化问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢Amit,

    遗憾的是,我们太靠近生产启动,已经进行了大量的可靠性测试,无法进行任何重大更改。 该项目以MSP432作为试验微型产品开始,我们非常清楚从注册表更新API命令所带来的风险。不希望出现任何未知的影响。 不是在寻找一个超级详细的评论,只是关于ADC ISR优先级,ISR等的任何明显的错误或问题。我并不是说上面发布的代码有任何问题。 只是一个健全的检查。

    最佳,
    Bob

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Bob,您好!

    请您也共享通道IO的配置。 请注意,由于我们只有LaunchPad,我们可能无法提供所有可能的配置测试。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Amit:

    当前与ADC相关的IO设置如下:

    	/*将ADC读数设置为使用ADC读取的输入*/
    	MAP_GPIO _setAsInputPin (GPIO_PORT_P4, GPIO _PIN2);
    	MAP_GPIO _setAsInputPin (GPIO_PORT_P4, GPIO _PIN3);
    	MAP_GPIO _setAsInputPin (GPIO_PORT_P4), GPIO _PIN4);
    	MAP_GPIO _setAsInputPin (GPIO端口P4,GPIO _PIN5);
    	MAP_GPIO _setAsInputPin (GPIO端口P4,GPIO _PIN6);
    	MAP_GPIO设置输入引脚(GPIO_PORT_P4,GPIO_PIN7);
    	MAP_GPIO设置输入引脚(GPIO_PORT_P5,GPIO_PIN2);
    	MAP_GPIO设置输入引脚(GPIO_PORT_P5, GPIO _PIN5);
    
    	/*将ADC引脚设置为低电压,这样剩余电压不会影响ADC读数*/
    	MAP_GPIO设置输出引脚(GPIO_PORT_P4,GPIO _PIN0);
    	MAP_GPIO设置输出引脚(GPIO_PORT_P4,GPIO _PIN1);
    	MAP_GPIO设置输出引脚(GPIO_PORT_P5, GPIO _PIN0);
    	MAP_GPIO _setAsOutputPin (GPIO端口_P5,GPIO _PIN1);
    	MAP_GPIO _setAsOutputPin (GPIO端口_P5,GPIO _PIN3);
    	MAP_GPIO设置输出引脚(GPIO_PORT_P5, GPIO_PIN4);
    	MAP_GPIO设置输出低引脚(GPIO_PORT_P4, GPIO_PIN0);
    	MAP_GPIO设置输出低引脚(GPIO_PORT_P4, GPIO _PIN1);
    	MAP_GPIO _setOutputLowOnPin (GPIO端口_P5,GPIO _PIN0);
    	MAP_GPIO _setOutputLowOnPin (GPIO端口_P5,GPIO _PIN1);
    	MAP_GPIO_setOutputLowOnPin (GPIO端口_P5,GPIO _PIN3);
    	MAP_GPIO _setOutputLowOnPin (GPIO端口_P5,GPIO _PIN4); 

    如您所见,并非所有ADC通道0-13都用于实际读数。 我们发现某些ADC引脚之间存在有意留下的空间,导致ADC引脚彼此相邻时产生某种"残余电容"噪声。

    下图显示了正在读取ADC信号的节点。

    在所有这些设置之前,我们初始化了IOS,如下所示:

    //终止设备上的所有其余引脚
    //	P1DIR |= 0xFF;P1OUT = 0;
    P2DIR |= 0xFF;P2OUT = 0;
    P3DIR |= 0xFF;P3OUT = 0;
    P4DIR |= 0xFF;P4OUT = 0;
    P5DIR || 0xFF;P5OUT = 0;
    P6DIR |= 0xFF;P6OUT = 0;
    P7DIR |= 0xFF;P7OUT = 0;
    P8DIR |= 0xFF;P8OUT = 0;
    P9DIR || 0xFF;P9OUT = 0;
    P10DIR |= 0xFF;P10OUT = 0; 

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    首先,很抱歉回复延迟。 我必须更改部分代码以满足我的LaunchPad要求,并且必须假定数据变量。 该代码有一个问题,即ISR中的中断源未被清除,导致其成为重入函数,且内存被覆盖。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好Amit:

    非常感谢您的评论。 请你详细说明这个问题吗? 设计目的是尽可能快地更新ADC ISR内的ADC变量(Life_off1,A0Results[X]等),以便主环路进行处理。 因此,只要用新的ADC值更新变量,我就可以了。 从技术上讲,它是否执行了以下操作:

    (UINT16_t) old_adc_value ->(uint16_t) 0 (短时间)->(uint16_t) new_ADC值

    那么这将是令人关切的。 但我认为它应该直接取代所有的价值,然后跳回到主要的循环。  

    old_adc_value -> new_adc值

    我是否正确理解这一点,或者是否发生了其他事情? 也许我应该在每个主环路上只调用一次ADC ISR。

    最佳,
    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好Robert

    我仍然不清楚为什么需要最快的环路,如果测试的目的是检查ADC输入
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    查看实施后,我想不一定需要尽快运行。  所以我测试了一个修改来初始化_ADC()

    已从更改

    ADC14_CTL0_CONSEQ_3 ((UINT32_t)0x6万)/*!<重复通道序列*/ 

    ADC14_CTL0_CONSEQ_1 (((UINT32_t)0x2万)/*!<信道序列*/ 

    然后我打电话:

    		ADC14->CTL0 |= ADC14_CTL0_ENC |/*!<		ADC14启用转换-与MAP_ADC14_ToggleConversionTrigger()相同;*/
    				ADC14_CTL0_SC;					/*!< ADC14开始转换*/
    

    在我的主循环开始时,在每次计算之前进行测量。

    这是您推荐的吗?  另一个实施不一定是错误的,但它是吗? 之所以这样实施,是因为我不想每次在主环路和计时器ISR例程中需要更新ADC值集时调用上面的enable ADC转换命令。  

    我想我不理解您的意思:  即,ISR中的中断源未被清除,导致其成为重入函数,内存被覆盖。  如何清除ADC ISR?

    最佳,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好Robert

    是的,这是我的建议,因为目的是测试模拟针脚。

    对于最后一个POST的第二部分,ADC的中断处理程序(ISR)中没有清除中断源。 必须根据中断条件写入ADC14CLRIFGR0或ADC14CLRIFGR1寄存器。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Amit:

    参考MSP432P4xx代码示例下的MSP432示例"msp432p401x_adc14_06.c"。

    下面是ADC ISR例程:

    // ADC14中断服务例程
    void ADC14_IRQHandler(void){
    
    IF (ADC14->IFGR0 & ADC14_IFGR0_IFG3)
    {
    A0results[index]= ADC14->MEM[0];//移动A0结果,IFG被清除
    A1results[index]= ADC14->MEM[1];//移动A1结果,IFG被清除
    A2results[index]= ADC14->MEM[2];//移动A2结果,IFG被清除
    A3results[index]= ADC14->MEM[3];//移动A3结果,IFG被清除
    索引=(索引+ 1)和0x7; //递增结果索引,模数
    __no_operation(); //在此处设置断点1
    }
    } 

    没有清除您提到的ISR,而ISR是我的代码所依据的。

    这是否不正确? 我一直认为您必须清除ISR。

    执行以下操作是否足够:

    /* ADC14中断服务例程*/
    void ADC14_IRQHandler (void){
    
    	uint64_t status;
    状态= MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag (状态);
    
    	IF (状态和ADC14->IFGR0 & ADC14_IFGR0_IFG13)
    	{
    		A0results[0]= ADC14->MEM[0];
    		Y1_sim = A0results[0];
    		A0results[1]= ADC14->MEM[1];[ADC14]
    		结果=[MA014]
    		
    		y2_sim = A0results[3];
    		A0results[4]= ADC14->MEM[4];
    		A0results[5]= ADC14->MEM[5];
    		temp = A0results[5];
    		Life_off1[0]= ADC14->MEM[6];
    		Lift_off1[1]= ADC14->MEM[7];
    		Lift_off1[2]= ADC14->MEM[8];
    		Lift_off2[0]= ADC14->MEM[9];
    		Lift_off2[1]= ADC14->MEM[10];Lift_off2[1]= ADC14->MEM[10];
    		Lift_off2[2]= ADC11_EM[14]
    		A0results[12]= ADC14->MEM[12];
    		A0results[13]= ADC14->MEM[13];
    	}
    
    

    
    

    最佳,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    第一个代码不写入ADC14IFGCLRx寄存器,而第二个例程写入。 您所引用的示例似乎不是来自SimpleLink MSP432P4 SDK。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    否第一个示例来自MSP432Ware。 这是否意味着我们使用MSP432Ware是正确的? 我将通过简单的第二个示例来说明这一点。

    Amit感谢您在整个过程中的所有帮助。  我们这里的团队对此非常赞赏。

    祝您2018年一切顺利!

    此致,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    我没有使用MSP432Ware,只使用了SimpleLink SDK。 我确实希望MSP432Ware是正确的,但我不能肯定地说,因为我们在实际实施时看到了我们的示例代码的问题。 但是,在报告时,我们会纠正它。 由于向前发展的软件平台是SDK,因此可能无法对MSP432Ware进行任何更新。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Amit:

    我尝试清除ADC ISR时遇到了一个问题,现在我不确定什么是正确的。

    以下代码有效(如果循环,请注意)

    /* ADC14中断服务例程*/
    void ADC14_IRQHandler (void){
    
    	uint64_t status;
    状态= MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag (状态);
    
    	IF (状态和ADC14_IFGR0_IFG13)
    	{
    		A0results[0]= ADC14->MEM[0];
    		Y1_sim = A0results[0];
    		A0results[1]= ADC14->MEM[1];
    		A0results[2]= ADC14->MEM[3]
    		;MA014=3
    		y2_sim = A0results[3];
    		A0results[4]= ADC14->MEM[4];
    		A0results[5]= ADC14->MEM[5];
    		temp = A0results[5];
    		Life_off1[0]= ADC14->MEM[6];
    		Lift_off1[1]= ADC14->MEM[7];
    		Lift_off1[2]= ADC14->MEM[8];
    		Lift_off2[0]= ADC14->MEM[9];
    		Lift_off2[1]= ADC14->MEM[10];Lift_off2[1]= ADC14->MEM[10];
    		Lift_off2[2]= ADC11_EM[14]
    		A0results[12]= ADC14->MEM[12];
    		A0results[13]= ADC14->MEM[13];
    	}
    

    但是,以下情况不会:

    /* ADC14中断服务例程*/
    void ADC14_IRQHandler (void){
    
    	uint64_t status;
    状态= MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag (状态);
    
    	IF (状态和ADC14->IFGR0 & ADC14_IFGR0_IFG13)
    	{
    		A0results[0]= ADC14->MEM[0];
    		Y1_sim = A0results[0];
    		A0results[1]= ADC14->MEM[1];[ADC14]
    		结果=[MA014]
    		
    		y2_sim = A0results[3];
    		A0results[4]= ADC14->MEM[4];
    		A0results[5]= ADC14->MEM[5];
    		temp = A0results[5];
    		Life_off1[0]= ADC14->MEM[6];
    		Lift_off1[1]= ADC14->MEM[7];
    		Lift_off1[2]= ADC14->MEM[8];
    		Lift_off2[0]= ADC14->MEM[9];
    		Lift_off2[1]= ADC14->MEM[10];Lift_off2[1]= ADC14->MEM[10];
    		Lift_off2[2]= ADC11_EM[14]
    		A0results[12]= ADC14->MEM[12];
    		A0results[13]= ADC14->MEM[13];
    	}
    

    ISR内IF语句的差异似乎是导致问题的原因。  仅当我放下:

    ADC14->IFGR0 

    关于逻辑,是否可以删除此项?  显然,上面的IFGR0代表/*!<中断标志0寄存器*/

    我试图将前面显示的MSP432Ware示例代码与您的建议混合使用,以清除ADC ISR标志,但没有成功,除非我这样做。

    请提供建议。

    此致,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    执行语句时:

    IF (状态和ADC14->IFGR0 & ADC14_IFGR0_IFG13)

    MAP_ADC14_clearInterruptFlag已清除中断标志,因此ADC14->IFGR0将返回0,导致“&”被评估为0,因此IF循环不会执行。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢Amit,

    这很令人困惑,为什么MSP432Ware的示例一开始就会这样写?

    IF (ADC14->IFGR0 & ADC14_IFGR0_IFG13) 

    似乎不应该清除中断标志... 它是否与ADC被设置为重复通道序列这一事实有关?

    ADC14_CTL0_CONSEQ_3 ((UINT32_t) 0x6万) /*!<重复通道序列*/ 

    您似乎认为这是正确的实施方式?

    /* ADC14中断服务例程*/
    void ADC14_IRQHandler (void){
    
    	uint64_t status;
    	status = MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag (状态);
    
    	IF (状态和ADC14_IFGR0_IFG13)
    	{
    		A0results[0]= ADC14->MEM[0];
    		Y1_sim = A0results[0];
    
    ...
    ... 

    最佳,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    当然可以。 您显示的最后一个代码是实施ISR的正确方法。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的,明白了,谢谢。

    关于SDK的最后一个问题:

    在MSP432 SDK的示例中。 "adc14_single conversion _repee.c",以下是作为ISR实现的。

    //![单个示例结果]/*
    ADC中断处理程序。 只要
    ADC_MEM0的转换*完成,就会调用该处理程序。
    */
    void ADC14_IRQHandler (void)
    {
    UINT64_t status = MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag (状态);
    
    IF (ADC_INT0和状态)
    {
    curADCResult = MAP_ADC14_getResult(ADC_MEM0);
    normalizedADCRes =(curADCResult * 3.3)/ 1.6384万;
    
    MAP_ADC14_toggleConversionTrigger();}
    
    } 

    在此ISR内,在接近例程结束时调用toggleConvertionTrigger()函数。 这显然是因为他们将采样计时器设置为ADC_MANUAL_ITED,(单采样模式配置),并且在IF循环结束时需要调用ADC14_toggleConversionTrigger(),以使重复发生。 然而,在我看来,这似乎是一种非常迂回的方式来重复单个信道。 为什么不将其设置为ADC_AUTOMATICATE_IREATTEND方法? 使用手动方法似乎很奇怪...

    最佳,

    罗伯特

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    我不确定目的是什么,但是将示例作为框架可能是使用MAP_ADC14_ToggleConversionTrigger调用的驱动因素。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    理解,谢谢Amit。
    非常感谢您的帮助。

    此致,
    罗伯特