********************************************************************************
* 详细说明:
* 此示例显示如何使用从 eTimer0 模块通道 2 触发的 CTU 模块。
*
* 有关 CTU 工作原理的详细信息,我建议您查看应用说明
*MPC5643LPWM_ADC_概念
* https://community.freescale.com/docs/DOC-102559
*
* 此示例设置 eTimer0 通道 2 用于 PWM 信号生成。
* 该信号用于将 MSR 触发信号发送到 CTU 模块
* 示例还包含简单的 CTU 模块驱动程序初始化
* CTU 调度器子模块根据 CTU 触发器通过外部引脚进行切换
*
* ------------------------------------------------------------------------------
* Test HW: MPC57xx Motherboard + MPC5744PE257DC minimodule, MPC5744P,
* 硅掩模套装 1N65H
* 目标:internal_FLASH*
********************************************************************************
Hi,
我们也遇到过类似的问题。有任何推荐的解决方案吗?
多谢!
Hi Linuxz,
我们最近确实遇到了类似的问题,您解决了吗?您能就此问题向我们提供一些反馈吗?
先行致谢。
[Peter] – 嗯,如果在已经有命令正在处理时发出 ADC 命令,则会设置 ADC_OE 标志(ADC 命令生成溢出错误)。
我觉得你的CTU命令列表存在时序问题。你写道:“我有时可以看到第一个命令是由ADC执行的”。有时这意味着什么?是指当占空比发生变化时,或者当这种情况发生时,情况会有什么不同。
Hi,
我对 MPC5744P 的 CTU 有疑问,我在 FlexPWM_0 上设置了 3 个同步 PWM 信号来控制 PMSM 电机。
为了控制该电机,我还需要测量 PWM 周期中特定位置的电流。
我尝试设置 PWM 子模块 0 来生成 OUT_TRIG0,并配置 CTU 以在 ADC 上启动双重转换,但由于我需要在我的设计中转换更多的模拟信号,所以我创建了一个 CTU 应该发送到 ADC 的命令列表。
当 6 个命令完成后,dma 传输将把数据移动到我的阵列中。
但有些地方不对劲,我有时可以看到第一个命令由 ADC 执行,结果移回到 CTU FIFO,但之后一切似乎都停止了,并且在 CTU 中设置了 ADC_OE 和 ERRCMP 标志。
关于我的代码出了什么问题,有什么提示吗?
请参阅下面的我的代码,找不到附加它的方法。
谨致问候 Linus
#包括“mpc55xx.h”
#包括“pwm_driver.h”
/* ************************************************************************** *
* 全局声明 *
* ************************************************************************** */
uint32_t ADC_结果[16];
/**
* @brief 设置PWM占空比
* @Param chn1 无符号值,包含通道 1 的占空比,范围为 0 至 1000
* @Param chn2 无符号值,包含通道 2 的占空比,范围为 0 至 1000
* @Param chn3 无符号值,包含通道 3 的占空比 0 至 1000
* @return boolean 值,1 = 成功,0 = 无法设置职责
*
* @details 当需要设置占空比时调用该函数
*/
boolean Pwm_SetDutyCycle (uint16 chn1, uint16 chn2, uint16 chn3)
{
if (chn1 > 950) chn1 = 950;
if (chn1 < 50) chn1 = 50;
if (chn2 > 950) chn2 = 950;
if (chn2 < 50) chn2 = 50;
if (chn3 > 950) chn3 = 950;
if (chn3 < 50) chn3 = 50;
if (FLEXPWM_0.MCTRL.B.LDOK == 0)
{
FLEXPWM_0.SUB[0].VAL[2].B.VAL = 5000 - (chn1*5);
FLEXPWM_0.SUB[0].VAL[3].B.VAL = 5000 + (chn1*5);
FLEXPWM_0.SUB[1].VAL[2].B.VAL = 5000 - (chn2*5);
FLEXPWM_0.SUB[1].VAL[3].B.VAL = 5000 + (chn2*5);
FLEXPWM_0.SUB[2].VAL[2].B.VAL = 5000 - (chn3*5);
FLEXPWM_0.SUB[2].VAL[3].B.VAL = 5000 + (chn3*5);
/* 将值锁存到 pwm 模块 */
FLEXPWM_0.MCTRL.B.LDOK |= 7;
return 1;
} else
{
return 0;
}
}
/**
* @brief pwm_Init
*
* @details 调用该函数来设置用于控制电机的 pwm 输出
*/
void pwm_Init(void)
{
SIUL2.PCR[46].R = 0x30000000 | 0x02000000 | 0x2; // CTU0 外部触发输出(在 EVB 上为 PG[13])
// 清除 LDOK 以便能够修改寄存器设置
FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 0;
FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 1;
FLEXPWM_0.MCTRL.B.CLDOK |= 1 << 2;
FLEXPWM_0.SUB[0].CTRL.B.PRSC = 5;
FLEXPWM_0.SUB[1].CTRL.B.PRSC = 0;
FLEXPWM_0.SUB[2].CTRL.B.PRSC = 0;
FLEXPWM_0.SUB[0].CTRL2.B.重新加载_SEL = 0;
FLEXPWM_0.SUB[1].CTRL2.B.RELOAD_SEL = 1; /* 来自子模块 0 的 RELOAD 信号用于重新加载寄存器*/
FLEXPWM_0.SUB[2].CTRL2.B.RELOAD_SEL = 1; /* 来自子模块 0 的 RELOAD 信号用于重新加载寄存器*/
FLEXPWM_0.SUB[0].CTRL2.B.CLK_SEL = 0; /* 外设时钟作为本地预分频器和计数器的时钟。*/
FLEXPWM_0.SUB[1].CTRL2.B.CLK_SEL = 2; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
FLEXPWM_0.SUB[2].CTRL2.B.CLK_SEL = 2; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
// FLEXPWM_0.SUB[0].CTRL2.B.FORCE_SEL = 0; /* 外设时钟用作本地预分频器和计数器的时钟。*/
// FLEXPWM_0.SUB[1].CTRL2.B.FORCE_SEL = 1; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
// FLEXPWM_0.SUB[2].CTRL2.B.FORCE_SEL = 1; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
// FLEXPWM_0.SUB[0].CTRL2.B.INIT_SEL = 0; /* 外设时钟用作本地预分频器和计数器的时钟。*/
// FLEXPWM_0.SUB[1].CTRL2.B.INIT_SEL = 1; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
// FLEXPWM_0.SUB[2].CTRL2.B.INIT_SEL = 1; /* 子模块 0 的时钟 (AUX_CLK) 用作本地预分频器和计数器的源时钟。*/
FLEXPWM_0.SUB[0].DISMAP.R = 0x0000; /* 禁用故障引脚条件 */
FLEXPWM_0.SUB[1].DISMAP.R = 0x0000; /* 禁用故障引脚条件 */
FLEXPWM_0.SUB[2].DISMAP.R = 0x0000; /* 禁用故障引脚条件 */
FLEXPWM_0.SUB[0].INIT.B.INIT = 0;
FLEXPWM_0.SUB[0].VAL[0].B.VAL = 20;
FLEXPWM_0.SUB[0].VAL[1].B.VAL = 10000;
FLEXPWM_0.SUB[0].VAL[2].B.VAL = 5000;
FLEXPWM_0.SUB[0].VAL[3].B.VAL = 5000;
FLEXPWM_0.SUB[0].TCTRL.B.OUT_TRIG_EN = 1; /* 当计数器值与 VAL0 值匹配时,OUT_TRIG0 将设置。*/
FLEXPWM_0.SUB[1].INIT.B.INIT = 0;
FLEXPWM_0.SUB[1].VAL[0].B.VAL = 20;
FLEXPWM_0.SUB[1].VAL[1].B.VAL = 10000;
FLEXPWM_0.SUB[1].VAL[2].B.VAL = 5000;
FLEXPWM_0.SUB[1].VAL[3].B.VAL = 5000;
FLEXPWM_0.SUB[2].INIT.B.INIT = 0;
FLEXPWM_0.SUB[2].VAL[0].B.VAL = 20;
FLEXPWM_0.SUB[2].VAL[1].B.VAL = 10000;
FLEXPWM_0.SUB[2].VAL[2].B.VAL = 5000;
FLEXPWM_0.SUB[2].VAL[3].B.VAL = 5000;
/*
FLEXPWM_0.SUB[0].DTCNT0.B.DTCNT0 = 0x0078;
FLEXPWM_0.SUB[0].DTCNT1.B.DTCNT1 = 0x0078;
FLEXPWM_0.SUB[1].DTCNT0.B.DTCNT0 = 0x0078;
FLEXPWM_0.SUB[1].DTCNT1.B.DTCNT1 = 0x0078;
FLEXPWM_0.SUB[2].DTCNT0.B.DTCNT0 = 0x0078;
FLEXPWM_0.SUB[2].DTCNT1.B.DTCNT1 = 0x0078;
*/
FLEXPWM_0.SUB[0].DTCNT0.B.DTCNT0 = 0x0;
FLEXPWM_0.SUB[0].DTCNT1.B.DTCNT1 = 0x0;
FLEXPWM_0.SUB[1].DTCNT0.B.DTCNT0 = 0x0;
FLEXPWM_0.SUB[1].DTCNT1.B.DTCNT1 = 0x0;
FLEXPWM_0.SUB[2].DTCNT0.B.DTCNT0 = 0x0;
FLEXPWM_0.SUB[2].DTCNT1.B.DTCNT1 = 0x0;
FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 0;
FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 1;
FLEXPWM_0.OUTEN.B.PWMA_EN |= 1 << 2;
FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 0;
FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 1;
FLEXPWM_0.OUTEN.B.PWMB_EN |= 1 << 2;
FLEXPWM_0.MCTRL.B.LDOK |= 1 << 0;
FLEXPWM_0.MCTRL.B.LDOK |= 1 << 1;
FLEXPWM_0.MCTRL.B.LDOK |= 1 << 2;
FLEXPWM_0.MCTRL.B.运行 |= 1 << 0;
FLEXPWM_0.MCTRL.B.运行 |= 1 << 1;
FLEXPWM_0.MCTRL.B.运行 |= 1 << 2;
/** 启用 PWM */
Enable_pwm();
}
/***********************************************************************/
/* CTU_初始化 */
/***********************************************************************/
void CTU_Init (void)
{
CTU_0.TGSISR.B.I1_RE = 0x1; /* 为 CTU 选择 MRS - PWM ch0 奇数 - 周期 50usec */
CTU_0.CR.B.TGSISR_RE = 0x1; /* TGS输入选择寄存器重新加载使能 */
CTU_0.TGSCR.B.PRES = 0x4; /* CTU预分频器设置为1 */
CTU_0.TCR[0].R = 0x10; /* CTU定时器比较寄存器0值 */
CTU_0.TGSCCR.R = 0xFFFF; /* TGS计数器比较寄存器 */
CTU_0.TGSCRR.R = 0; /* TGS计数器重载寄存器 */
CTU_0.TGSCR.B.TGS_M = 0;
CTU_0.TGSCR.B.ET_TM = 0;
CTU_0.THCR1.B.T0_E = 1; /* 触发器 0 输出使能 */
CTU_0.THCR1.B.T0_ADCE = 1; /* 触发 0 ADC 命令输出使能 */
CTU_0.CLCR1.B.T0_INDEX = 0; /* 触发器 0 命令列表 - 第一个命令地址 */
//(*(volatile uint16_t *)0xFFE0C06C) = 1; /* CTU_0.FDCR = 1 - FIFO 上可用的 DMA(头文件中缺失!)*/
CTU_0.FDCR.B.DE0 = 1;
CTU_0.FCR.R = 0; /* FIFO控制寄存器 */
/* CTU触发ADC - ADC命令列表 */
/* SU:ADC命令列表*/
//CTU_0.CLR[0].R = 14; /* 第一个命令 - CTU 在该命令之后开始向 ADC 发送命令 */
//CTU_0.CLR[0].ABCH = 5; /* ADC_0 模块,通道 11 */
//CTU_0.CLR[0].B.B.CMS = 0;
//CTU_0.CLR[0].B.B.LC = 1;
CTU_0.CLR[0].BBCH_A = 11; /* ADC_0模块,通道11 */
CTU_0.CLR[0].B.B.CH_B = 12; /* ADC_1 module, channel 12 */
CTU_0.CLR[0].B.B.CMS = 1;
CTU_0.CLR[1].BBCH_A = 13; /* ADC_0模块,通道13 */
CTU_0.CLR[1].B.B.CH_B = 1; /* ADC_1 module, channel 1 */
CTU_0.CLR[1].B.B.CMS = 1;
//CTU_0.CLR[1].B.B.LC = 1;
CTU_0.CLR[2].BBCH_A = 5; /* ADC_0模块,通道5 */
CTU_0.CLR[2].B.B.CH_B = 0; /* ADC_1 module, channel 0 */
CTU_0.CLR[2].B.B.CMS = 1;
CTU_0.CLR[3].BBCH_A = 14; /* ADC_0模块,通道14 */
CTU_0.CLR[3].B.B.CH_B = 2; /* ADC_1 module, channel 2 */
CTU_0.CLR[3].B.B.CMS = 1;
CTU_0.CLR[4].BBCH_A = 10; /* ADC_0模块,通道10 */
CTU_0.CLR[4].B.B.CH_B = 15; /* ADC_1 module, channel 15 */
CTU_0.CLR[4].B.B.CMS = 1;
CTU_0.CLR[5].BBCH_A = 15; /* ADC_0模块,通道15 */
CTU_0.CLR[5].B.B.CH_B = 10; /* ADC_1 module, channel 10 */
CTU_0.CLR[5].B.B.CMS = 1;
CTU_0.CLR[6].AR = 0x4000; /* 最后一条命令 - 该命令不发送到 ADC */
CTU_0.FTH.B.TH0 = 5;
//CTU_0.FTH.B.TH0 = 5;
//CTU_0.TH1.B.THRESHOLD0 = 0xE; /* FIFO 0 阈值。最大值为 15,因为阈值必须小于 FIFO 0 条目的数量。*/
//CTU_0.FCR.B.FIFO_OVERFLOW_EN0 = 1; /* FIFO 0 阈值溢出中断启用 - 在此中断中读取 FIFO 0 */
CTU_0.EFR.R = 0x0400; /*启动前清除标志*/
CTU_0.IFR.R = 0x01FE;
CTU_0.CR.B.GRE = 1; /* 通用重新加载启用 */
//CTU_初始化
/***********************************************************************/
/* ADC_初始化 */
/***********************************************************************/
void ADC_Init (void)
{
/* 使用_ADC */
ADC_0.MCR.B.PWDN = 0; // Enable ADC0
/* 1 */
ADC_0.MCR.B.CTUEN = 1; // CTU mode
/* 2 */
ADC_0.NCMR[0].R = 0xFFFF; //ADC_0通道0
ADC_0.MCR.B.MODE = 1; //单次模式
ADC_1.MCR.B.PWDN = 0; // Enable ADC1
/* 1 */
ADC_1.MCR.B.CTUEN = 1; // CTU mode
/* 2 */
ADC_1.NCMR[0].R = 0xFFFF; //ADC_1通道0
ADC_1.MCR.B.MODE = 1; //单次模式
} //ADC初始化
/***********************************************************************/
/* DMA_Init */
/***********************************************************************/
void DMA_Init (void)
{
DMA_0.CR.R = 0x00000002; /* 启用调试模式 */
DMA_0.EEI.R = 0x0000; /* 所有通道禁用错误中断 */
DMA_0.ERQ.B.ERQ0 = 1 << 2; /*使用通道 2 *//*启用 eDMA 请求 2 -> CTU FIFO_0 触发 */
}//DMA_初始化
/***********************************************************************/
/* DMA_MUX_初始化 */
/***********************************************************************/
void DMA_MUX_Init(void)
{
DMAMUX_0.CHCFG[2].R = 0x0000; /*清除通道配置寄存器2*/
DMAMUX_0.CHCFG[2].B.SOURCE = 6; /* 为通道 2 选择 MUX 源 -> CTU FIFO_1 */
DMAMUX_0.CHCFG[2].B.ENBL = 1; /* DMA 通道使能 */
//DMA_MUX_初始化
/***********************************************************************/
/* DMA_TCD_2 */
/***********************************************************************/
void DMA_TCD_2(void)
{
(*(volatile uint16 *)&DMA_0.TCD[2]) = 0x0; //清除DMA.TCD[0]0.WORD7
//DMA_0.TCD[2] = 0x0;
DMA_0.TCD[2].SADDR.B.SADDR = &CTU_0.FR[0]; /* Source Address - CTU FIFO_0 */
DMA_0.TCD[2].DADDR.B.DADDR = (uint32_t) &ADC_results[0]; /* 目标地址 - SRAM */
DMA_0.TCD[2].ATTR.B.SMOD = 0x0; /* 源地址模数 */
DMA_0.TCD[2].ATTR.B.DMOD = 0x0; /* Destination Address Modulo */
DMA_0.TCD[2].ATTR.B.SSIZE = 0x2; /*源传输大小:32位*/
DMA_0.TCD[2].ATTR.B.DSIZE = 0x2; /* 目标传输大小:32 位 */
DMA_0.TCD[2].SOFF.B.SOFF = 0x0; /*有符号源地址偏移调整*/
DMA_0.TCD[2].NBYTES.MLOFFNO.B.NBYTES = 0x40; /* 内部‘次要’字节数 */
DMA_0.TCD[2].SLAST.B.SLAST = 0x0; /* 最后签名的源地址调整 */
DMA_0.TCD[2].DOFF.B.DOFF = 0x4; /* 有符号目标地址偏移 */
DMA_0.TCD[2].DLASTSGA.B.DLASTSGA = 0xFFFFFFC0; /* 有符号目标地址偏移量 -64 */
DMA_0.TCD[2].BITER.ELINKNO.B.ELINK = 0x0; /* 小循环完成时的通道间链接:禁用*/
DMA_0.TCD[2].BITER.ELINKNO.B.BITER = 0x1; /* 当前主迭代计数或链路通道号 */
DMA_0.TCD[2].CITER.ELINKYES.B.ELINK = 0x0; /* 小循环完成时的通道间链接:禁用*/
DMA_0.TCD[2].CITER.ELINKYES.B.LINKCH = 0x0; /* 小循环上通道间链接的通道号:未完成*/
DMA_0.TCD[2].CITER.ELINKYES.B.ELINK = 0x0001; /* 当前主迭代计数或链接通道号 */
DMA_0.TCD[2].CSR.B.BWC = 0x00; /* 带宽控制 */
DMA_0.TCD[2].CSR.B.MAJORLINKCH = 0x00; /* 主通道号 */
DMA_0.TCD[2].CSR.B.MAJORELINK = 0x00; /*主循环完成时的通道间链接:禁用*/
DMA_0.TCD[2].CSR.B.DONE = 0x00; /* 通道完成位 */
DMA_0.TCD[2].CSR.B.ACTIVE = 0x00; /* 通道活动位 */
DMA_0.TCD[2].CSR.B.ESG = 0x00; /* 启用分散/聚集:禁用*/
DMA_0.TCD[2].CSR.B.DREQ = 0x00; /* 完成时禁用DMA通道:禁用*/
DMA_0.TCD[2].CSR.B.INTHALF = 0x00; /* 半主计数完成中断:禁用*/
DMA_0.TCD[2].CSR.B.INTMAJOR = 0x01; /* 主循环完成中断:禁用*/
DMA_0.TCD[2].CSR.B.START = 0x00; /* 显式通道启动位 */
//DMA_0