【RTD200P04 MCAL 篇3】 S32M244 PWM PDB ADC控制

一,文档简介

S32M2XX系列是专门为电机控制而生的MCU系列:
S32M24X,延续S32K14X系列MCU,添加了AE预驱模块。
S32M27X,延续了S32K3系列MCU,添加了AE预驱模块。
NXP官方提供了S32M24X和S32M27X系列的EVB,可以配合一个三相PMSM/BLDC电机,实现单电阻电流采样方式的电机控制。研究电机控制的必经之路是要懂得怎么去控制PWM,实现在特定时刻采集电流,电压信号,并且经过计算再回调PWM控制。本文将基于S32M24X-EVB:
https://www.nxp.com/design/design-center/development-boards-and-designs/S32M24XEVB
讲解如何实现在S32M244上,输出带有死区的互补PWM,并且使用FTM_INT作为触发信号,通过PDB延迟触发ADC采样,将ADC采集的值通过UART打印到PC串口,另外通过TRGMUX模块实现不同模块的相互连接,比如FTM和PDB,还有将信号通过TRGMUX_OUT引脚输出。实现的框图结构如下:PWM+TRGMUX+PDB+ADC 双通道。本文主要是使用MCAL的方式实现功能。
本人做的两个配套MCAL附件代码:
S32DSMCAL: Mcal_PWMPDBADC_S32M244_RTD200P04.zip
GCCMCAL: PWMPDBADC_TS_T40D2M20I0R0_kerry.zip
GCCMCAL,是使用ARM GCC makefile方式直接编译,可以参考工具篇的vscode方式去编译生成elf文件去烧录。
S32DSMCAL,是将EB MCAL工程集成到S32DS的工程中去的方式。
在这里插入图片描述

图 1

本文的主要目的是分享小编自己做的S32M244 MCAL PWM PDB ADC demo,因为目前还没有直接的对应的集成的M244 MCAL demo,如果熟悉电机控制的,也可以直接参考官方S32M244电机控制LLD demo自行去做,但是目前M244电机控制还没有MCAL demo。

二,PWM+TRGMUX+PDB+ADC 2ch 软件配置与实现

2.1 软硬件版本平台

硬件:S32M244-EVB
软件:

  • S32DS : S32DS.3.5_b220726_win32.x86_64.exe
  • Update 4 for S32DS:SW32_S32DS_3.5.4_D2307.zip
  • Development package for S32K1XX: SW32K1_S32DS_3.5.4_D2307.zip
  • Development package for S32M2XX: SW32M2xx_S32DS_3.5.0_D2303.zip
  • RTD:
    S32K1_S32M24X Real Time Drivers AUTOSAR 4.4 & R21-11 Version 2.0.0
    S32K1_S32M24X Real Time Drivers AUTOSAR R21-11 Version 2.0.0 P04
  • S32M24x_AMMCLIB_RTM_1_1_39_BIN
  • S32M24XEVB Evaluation Board Motor Control Application Software :
    S32M24XEVB-SW.exe
  • FreeMASTER tool 3.2 : FMASTERSW32.exe
  • VSCode
  • EB tresos studio 29.0

这里的软件平台是能够让电机demo都运行起来的这个平台, 如果不需要电机,只需要装S32DS, update,development,RTD,EB即可, VScode取决于个人工具使用习惯,酌情安装。
具体的软件链接,建议直接到官网对应软件下载的地方去搜索下载对应版本即可。

2.2 MCAL工程以及模块配置

本文对应了两种类型的MCAL 工程:

(1)直接在SW32K1_S32M24x_RTD_R21-11_2.0.0_P04现有的MCAL工程,拷贝一个,然后修改EB MCAL的配置,并且添加代码到main,通过makefile方式去编译生成elf,然后再去烧录elf的方式。
(2)新建S32DS工程,然后集成SW32K1_S32M24x_RTD_R21-11_2.0.0_P04驱动,以及EB生成的代码,再添加main代码,这种方式就可以直接在S32DS里面编译,并且烧录的方式。
关于两种方式的编译以及构建,小编有其他对应的工具篇文章详细讲解,自行查阅。
S32K3 工具篇6:如何将RTD EB工程导入到S32DS
S32K3 工具篇7:如何使用VScode编译EB MCAL工程
S32K3 工具篇8:如何移植RTD MCAL现有demo到其他K3芯片
对于EB工程,本例程使用到的相关模块如下:
在这里插入图片描述

图 2

BaseNXP, Dem, EcuC 模块属于基础模块,没有特别需要配置的,下面对重点模块具体讲解:

2.2.1 Dio 模块配置

   Dio主要用到PTE15作为LED引脚,对于PTE15,Port_Id=4, Dio Channel Id=15.

Port_Id, A=0, B=1,C=2,D=3,E=4…,Dio Channel Id是对应port中的引脚号。
在这里插入图片描述

图 3

2.2.2 Adc模块配置

Adc模块需要做ADC模块的配置,比如传输类型,分频系数,校准分频系数,转换分辨率,PDB硬件模块配置情况,ADC通道,ADC group,group里面要配置引脚触发源,通道延迟情况等,具体相关配置如下:

(1)AdcHwUnit
AdcHwUnit_0->General
在这里插入图片描述

图 4

主要几点,12位分辨率,然后PDB周期是8000,因为PDB用的是系统时钟80Mhz,所以是10K周期的PDB counter。
AdcHwUnit_0->AdcChannel
在这里插入图片描述

图 5

AdcChannel定义了两个通道,分别为SE11_ADCH11外部连接板载的可调电位器,还有一个是BANDGAP_ADCH27,是内部的bandgap 1V。
AdcHwUnit_0->AdcGroup
AdcGroup里面需要配置多个地方:
AdcHwUnit_0->AdcGroup0->General: 转换模式,触发模式,采样时间等。
在这里插入图片描述

图 6

AdcHwUnit_0->AdcGroup0->AdcChannelDelay:定义两个通道PDB触发延迟的时间,必须要满足单通道能够转换完的时间,否则会造成PDB错误。
在这里插入图片描述

图 7

AdcHwUnit_0->AdcGroup0->AdcGroupDefinition:定义group对应的通道情况
在这里插入图片描述

图 8

(2) AdcHwTrigger
在这里插入图片描述

图 9

(3) AdcInterrupt
在这里插入图片描述

图 10

2.2.3 Mcu模块配置

Mcu模块主要用于配置MCU的相关时钟McuClockSettingConfig,工作模式McuModeSettingConf.

McuClockSettingConfig时钟配置选项较多,不一一展开,可以参考附件代码。
在这里插入图片描述

图 11

这里需要注意下McuclockReferencePoint
在这里插入图片描述

图12

这里涉及到FTM,ADC, PDB, UART模块的时钟参考源情况。

2.2.4 Platform模块配置

Platform配置主要是Interrupt controller的配置:

在这里插入图片描述

图 13

添加对应模块的中断号和中断Handler。

2.2.5 Port模块配置

Port中配置了使用到的引脚端口,主要是PortContainer的配置,当前配置情况如下:
在这里插入图片描述

图 14

2.2.6 Pwm模块配置

Pwm模块配置有两个点:

(1)PwmChannel
在这里插入图片描述

图 15

(2) PwmFtm
PwmFtm_0->Ftm Modules
在这里插入图片描述

图 16

这里配置了边沿对齐模式,死区的时间为0.5us。
PwmFtm_0->Ftm Sync
在这里插入图片描述

图 17

PwmFtm_0->PwmFtmCh
在这里插入图片描述

图 18

配置为Combined Mode,互补输出,FTM0通道0和1.

2.2.7 Uart模块配置

Uart->UartChannel
在这里插入图片描述

图 19

2.3主程序调用情况

配置完成之后,可以通过在main中调用如下代码实现PWM触发PDB采集ADC双通道的情况,PWM可以输出互补信号,并且还可以实现相关的触发信号通过TRGMUX_OUT引脚输出:


#ifdef __cplusplus
extern "C" {
#endif

#include "Mcu.h"
#include "Port.h"
#include "Dio.h"
#include "Pwm.h"
#include "Platform.h"
#include "Adc.h"
#include "Mcl.h"
#include "Lpuart_Uart_Ip_Irq.h"
#include "CDD_Uart.h"
#include <string.h>
#include "stdio.h"
#include "retarget.h"
#include "check_example.h"

#define RESULT_ADC_BANDGAP    (1241U) /* Vbandgap ~ 1.0V at 3.3V reference */
#define NUM_RESULTS             (4u)

volatile uint32 VarNotification_0 = 0;
volatile uint32 pdberrcnt = 0;

extern ISR(Adc_0_Isr);

Adc_ValueGroupType    ResultBuffer[NUM_RESULTS] =  {0xaaaa, 0xaaaa,0xaaaa, 0xaaaa};
/* Used for ReadGroup */
Adc_ValueGroupType    AdcReadGroupBuffer[NUM_RESULTS] =  {0xbbbb, 0xbbbb,0xbbbb, 0xbbbb};

//UART
#define UART_LPUART_INTERNAL_CHANNEL  0U
#define WELCOME_MSG "Helloworld for automotive with S32M244!\r\n"
#define MSG_LEN  50U

void AdcNotification(void)
{
    VarNotification_0++;
}
void PDB_ADC_SEQ_ERR_NOTIFICATION()
{
    pdberrcnt ++;
}

void TestDelay(uint32 delay);
void TestDelay(uint32 delay)
{
   static volatile uint32 DelayTimer = 0;
   while(DelayTimer<delay)
   {
       DelayTimer++;
   }
   DelayTimer=0;
}

int main(void)
{
    uint8 count = 0U;
    Std_ReturnType StdReturn = E_NOT_OK;
    volatile boolean bStatus = TRUE;
    Adc_CalibrationStatusType CalibStatus;
    volatile Std_ReturnType T_Uart_Status1;

    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */

    /* Initialize the clock tree and apply PLL as system clock */
    Mcu_InitClock(McuClockSettingConfig_0);
#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }

    Mcu_DistributePllClock();
#endif
    Mcu_SetMode(McuModeSettingConf_0);

    /* Initialize all pins using the Port driver */
    Port_Init(NULL_PTR);
    Platform_Init(NULL_PTR);
    Platform_InstallIrqHandler(LPUART0_RxTx_IRQn, LPUART_UART_IP_0_IRQHandler, NULL_PTR);
    Pwm_Init(&Pwm_Config_VS_0);
    Mcl_Init(&Mcl_Config_VS_0);
    Adc_Init(&Adc_Config_VS_0);
    Uart_Init(NULL_PTR);

    /* Part 1: Example with SW Triggered One-Shot Conversion Mode, data conversion is updated by Interrupt.*/
    /*******************************************************************************************************/
    Adc_Calibrate(AdcHwUnit_0, &CalibStatus);
    if(CalibStatus.AdcUnitSelfTestStatus == E_NOT_OK)
    {
        bStatus = FALSE;
    }
    /* ResultBuffer is updated new data in Adc_0_Isr handler */
    Adc_SetupResultBuffer(AdcGroup_0, ResultBuffer);
    Adc_EnableGroupNotification(AdcGroup_0);
  //for ADC hardware
    Adc_EnableHardwareTrigger(AdcHwUnit_0);
    Adc_StartGroupConversion(AdcHwUnit_0);

    printf("S32M244 FTM TRIGMUX ADC demo RTD200P04!\r\n");
  
    while (1)
    {
        printf("===========New Round ADC sampling=========\r\n");
        /* Get input level of channels */
        Dio_WriteChannel(DioConf_DioChannel_DioChannel_LEDD20, STD_HIGH);
        TestDelay(2000000);
        TestDelay(2000000);
        Pwm_SetDutyCycle(PwmChannel_0, 0x2000);

        Dio_WriteChannel(DioConf_DioChannel_DioChannel_LEDD20, STD_LOW);
        TestDelay(2000000);
        TestDelay(2000000);
        Pwm_SetDutyCycle(PwmChannel_0, 0x6000);

         VarNotification_0 = 0;
         while(VarNotification_0 == 0)
         {}
         StdReturn = Adc_ReadGroup(AdcGroup_0, AdcReadGroupBuffer);
         printf("adc1_SE11 = %d \r\n",(int)AdcReadGroupBuffer[0]);
         printf("adc1_bandGap = %d \r\n",(int)AdcReadGroupBuffer[1]);
    }

    Exit_Example(TRUE);

    return (0U);
}

#ifdef __cplusplus
}
#endif

三, 测试结果

测试结果包括两部分:打印结果看ADC采样值情况,以及PWM输出和PDB触发位置的关系情况。打印结果如下,可以看到ADC的两个通道的值是正确的:
在这里插入图片描述

图 20

PWM波形测试情况如下:
CH1: PTC0
CH2: PTC1
CH3: PTD0
CH4: PTD1
CH5: PTE11
在这里插入图片描述

图 21

源码链接:
https://community.nxp.com/t5/S32M-Knowledge-Base/RTD200P04-MCAL-S32M244-PWM-PDB-ADC-MCAL-demo/ta-p/2076988

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值