TMS320C6748 完整API参考手册

基于CSDN博客系列文章整理   整理日期:2026-01-03


目录

  1. GPIO与定时器事件组合中断

  2. 定时器64位模式

  3. 定时器32位模式

  4. UART中断模式

  5. UART轮询模式

  6. EDMA+GPIO中断

  7. RS485通信

  8. I2C与EEPROM

  9. EDMA+SPI Flash

  10. PWM(eHRPWM)模块

  11. ECAP_APWM模式

  12. 看门狗定时器

  13. NMI不可屏蔽中断

  14. RTC实时时钟

  15. EMIF访问NAND Flash

  16. EMIF时钟配置


示例总结表

模块示例内容
1. GPIO+定时器事件组合中断GPIO按键中断+定时器中断LED控制完整示例
2. 定时器64位模式1秒周期定时器中断示例
3. 定时器32位模式双定时器独立运行示例 (1秒+500ms)
4. UART中断模式接收数据回显+FIFO配置示例
5. UART轮询模式UARTprintf格式化输出+UARTGets输入示例
6. EDMA+GPIO中断EDMA内存传输+传输完成中断示例
7. RS485通信半双工收发+GPIO方向控制示例
8. I2C与EEPROMAT24C02单字节/页读写完整示例
9. EDMA+SPI FlashW25Q16 Flash读写+扇区擦除示例
10. PWM(eHRPWM)模块10kHz PWM+占空比调节+死区控制示例
11. ECAP_APWM模式ECAP辅助PWM+占空比渐变示例
12. 看门狗定时器5秒超时+喂狗操作完整示例
13. NMI不可屏蔽中断紧急数据保存+安全模式示例
14. RTC实时时钟时间设置+闹钟+每秒中断示例
15. EMIF访问NAND FlashNAND Flash读/写/擦除完整示例
16. EMIF时钟配置PLL0_SYSCLK3分频配置+OBSCLK验证示例

1. GPIO与定时器事件组合中断

1.1 事件组合初始化

IntEventCombineInit()
 

void IntEventCombineInit(
    unsigned int ECM0,
    unsigned int ECM1,
    unsigned int ECM2,
    unsigned int ECM3
);

功能: 初始化事件组合器,将多个系统事件组合到一个CPU中断 参数:

  • ECM0-ECM3: 事件组合器0-3的配置

  • 使用 C674X_MASK_INTx 指定目标CPU中断

示例:

 

 
IntEventCombineInit(
    ECM0_UNUSED,      // 不使用ECM0
    C674X_MASK_INT4,  // ECM1映射到INT4
    ECM2_UNUSED,      // 不使用ECM2
    ECM3_UNUSED       // 不使用ECM3
);

1.2 中断注册与映射

IntRegister()
 

 
void IntRegister(unsigned int cpuInt, void (*handler)(void));

功能: 注册CPU可屏蔽中断的处理函数 参数:

  • cpuInt: CPU中断号 (C674X_MASK_INT4 ~ INT15)

  • handler: 中断服务函数指针

IntEventMap()
 

 
void IntEventMap(unsigned int cpuInt, unsigned int sysEvent);

功能: 将系统事件映射到CPU中断 参数:

  • cpuInt: CPU中断号

  • sysEvent: 系统事件号 (0-127)

IntEventSet()
 

 
void IntEventSet(unsigned int sysEvent);

功能: 将指定系统事件加入事件组合器 参数:

  • sysEvent: 系统事件号

IntEnable()
 

 
void IntEnable(unsigned int cpuInt);

功能: 使能CPU可屏蔽中断

IntGlobalEnable()
 

 
void IntGlobalEnable(void);

功能: 使能CPU全局中断 (设置CSR寄存器GIE位)

1.3 事件清除

IntEventClear()
 

 
void IntEventClear(unsigned int sysEvent);

功能: 清除系统事件标志 参数:

  • sysEvent: 系统事件号

IntEventCombineClear()
 

 
void IntEventCombineClear(unsigned int ECMx, unsigned int sysEvent);

功能: 清除事件组合器中的事件标志

1.4 GPIO配置

GPIODirModeSet()
 

 
void GPIODirModeSet(
    unsigned int baseAddr,
    unsigned int pinNumber,
    unsigned int pinDir
);

功能: 设置GPIO引脚方向 参数:

  • baseAddr: GPIO基地址 (SOC_GPIO_0_REGS)

  • pinNumber: 引脚号 (1-144)

  • pinDir: 方向 (GPIO_DIR_INPUT / GPIO_DIR_OUTPUT)

GPIO引脚编号规则:

Bank起始引脚号示例
GPIO0[0]1GPIO0[0] = 1
GPIO1[0]17GPIO1[0] = 17
GPIO6[0]97GPIO6[12] = 109
GPIOPinWrite()
 

 
void GPIOPinWrite(
    unsigned int baseAddr,
    unsigned int pinNumber,
    unsigned int bitValue
);

功能: 写GPIO输出电平 参数:

  • bitValue: GPIO_PIN_LOW / GPIO_PIN_HIGH

GPIOBankIntEnable()
 

 
void GPIOBankIntEnable(
    unsigned int baseAddr,
    unsigned int bankNumber
);

功能: 使能GPIO bank中断

GPIOIntTypeSet()
 

 
void GPIOIntTypeSet(
    unsigned int baseAddr,
    unsigned int pinNumber,
    unsigned int intType
);

功能: 设置GPIO中断触发类型 参数:

  • intType: 触发类型

    • GPIO_INT_TYPE_NOEDGE: 无边沿

    • GPIO_INT_TYPE_FALLEDGE: 下降沿

    • GPIO_INT_TYPE_RISEDGE: 上升沿

    • GPIO_INT_TYPE_BOTHEDGE: 双边沿

GPIOPinIntClear()
 

 
void GPIOPinIntClear(
    unsigned int baseAddr,
    unsigned int pinNumber
);

功能: 清除GPIO中断标志

1.5 完整应用示例

 

/****************************************************************************/
/*                             GPIO+定时器事件组合中断完整示例                    */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "gpio.h"
#include "timer.h"
#include "psc.h"
#include "soc_C6748.h"
/* 定义GPIO引脚 (GPIO6[12] = 109, GPIO6[13] = 110) */
#define GPIO_LED1_PIN    109
#define GPIO_LED2_PIN    110
#define GPIO_KEY_PIN     111    // GPIO6[14] = 111
/* 中断服务函数声明 */
void GPIOBankISR(void);
void Timer0ISR(void);
/* 全局变量 */
volatile unsigned int timerCount = 0;
/*---------------------------------------------------------------------------*/
/* PSC模块使能                                                                */
/*---------------------------------------------------------------------------*/
void PSCInit(void)
{
    /* 使能GPIO模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 使能Timer0模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TMR0, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
}
/*---------------------------------------------------------------------------*/
/* GPIO初始化                                                                 */
/*---------------------------------------------------------------------------*/
void GPIOInit(void)
{
    /* 配置LED引脚为输出 */
    GPIODirModeSet(SOC_GPIO_0_REGS, GPIO_LED1_PIN, GPIO_DIR_OUTPUT);
    GPIODirModeSet(SOC_GPIO_0_REGS, GPIO_LED2_PIN, GPIO_DIR_OUTPUT);
    /* 配置按键引脚为输入 */
    GPIODirModeSet(SOC_GPIO_0_REGS, GPIO_KEY_PIN, GPIO_DIR_INPUT);
    /* 初始状态:LED1亮,LED2灭 */
    GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED1_PIN, GPIO_PIN_HIGH);
    GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED2_PIN, GPIO_PIN_LOW);
    /* 配置按键中断:下降沿触发 */
    GPIOIntTypeSet(SOC_GPIO_0_REGS, GPIO_KEY_PIN, GPIO_INT_TYPE_FALLEDGE);
    /* 使能GPIO Bank6中断 */
    GPIOBankIntEnable(SOC_GPIO_0_REGS, 6);
}
/*---------------------------------------------------------------------------*/
/* 定时器初始化 (1秒周期)                                                      */
/*---------------------------------------------------------------------------*/
void TimerInit(void)
{
    /* 配置为64位模式 */
    TimerConfigure(SOC_TMR_0_REGS, TMR_CFG_64BIT_CLK_INT);
    /* 设置周期值 (24MHz时钟,1秒 = 24000000) */
    TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER12, 24000000);
    TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 0);
    /* 使能定时器中断 */
    TimerIntEnable(SOC_TMR_0_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}
/*---------------------------------------------------------------------------*/
/* 中断系统初始化                                                              */
/*---------------------------------------------------------------------------*/
void InterruptInit(void)
{
    /* 初始化DSP中断控制器 */
    IntDSPINTCInit();
    /* 初始化事件组合器: ECM1映射到INT4, ECM2映射到INT5 */
    IntEventCombineInit(ECM0_UNUSED,
                        C674X_MASK_INT4,    /* ECM1 -> INT4 (GPIO) */
                        C674X_MASK_INT5,    /* ECM2 -> INT5 (Timer) */
                        ECM3_UNUSED);
    /* 注册GPIO Bank6中断 (系统事件96) */
    IntRegister(C674X_MASK_INT4, GPIOBankISR);
    IntEventMap(C674X_MASK_INT4, SYS_INT_GPIO_B6INT);
    IntEventSet(SYS_INT_GPIO_B6INT);
    IntEnable(C674X_MASK_INT4);
    /* 注册Timer0中断 (系统事件4) */
    IntRegister(C674X_MASK_INT5, Timer0ISR);
    IntEventMap(C674X_MASK_INT5, SYS_INT_TIMER64P0_TINT12);
    IntEventSet(SYS_INT_TIMER64P0_TINT12);
    IntEnable(C674X_MASK_INT5);
    /* 使能全局中断 */
    IntGlobalEnable();
}
/*---------------------------------------------------------------------------*/
/* GPIO中断服务函数                                                            */
/*---------------------------------------------------------------------------*/
void GPIOBankISR(void)
{
    /* 清除GPIO中断标志 */
    GPIOPinIntClear(SOC_GPIO_0_REGS, GPIO_KEY_PIN);
    /* 翻转LED1 */
    if(GPIOPinRead(SOC_GPIO_0_REGS, GPIO_LED1_PIN))
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED1_PIN, GPIO_PIN_LOW);
    else
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED1_PIN, GPIO_PIN_HIGH);
    /* 清除事件组合器标志 */
    IntEventClear(SYS_INT_GPIO_B6INT);
}
/*---------------------------------------------------------------------------*/
/* 定时器中断服务函数                                                          */
/*---------------------------------------------------------------------------*/
void Timer0ISR(void)
{
    /* 清除定时器中断标志 */
    TimerIntStatusClear(SOC_TMR_0_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
    /* 计数器递增 */
    timerCount++;
    /* 翻转LED2 */
    if(timerCount % 2)
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED2_PIN, GPIO_PIN_HIGH);
    else
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED2_PIN, GPIO_PIN_LOW);
    /* 清除事件组合器标志 */
    IntEventClear(SYS_INT_TIMER64P0_TINT12);
}
/*---------------------------------------------------------------------------*/
/* 主函数                                                                     */
/*---------------------------------------------------------------------------*/
int main(void)
{
    /* 初始化PSC */
    PSCInit();
    /* 初始化GPIO */
    GPIOInit();
    /* 初始化定时器 */
    TimerInit();
    /* 初始化中断 */
    InterruptInit();
    /* 启动定时器 */
    TimerEnable(SOC_TMR_0_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
    /* 主循环 */
    while(1)
    {
        /* 等待中断 */
    }
}

2. 定时器64位模式

2.1 定时器配置

TimerConfigure()
 

 
void TimerConfigure(
    unsigned int baseAddr,
    unsigned int config
);

功能: 配置定时器工作模式 参数:

  • baseAddr: 定时器基地址 (SOC_TMR_0_REGS ~ SOC_TMR_3_REGS)

  • config: 配置模式

    • TMR_CFG_64BIT_CLK_INT: 64位模式,内部时钟

    • TMR_CFG_32BIT_UNCH_CLK_INT: 32位非链式模式

    • TMR_CFG_32BIT_CH_CLK_INT: 32位链式模式

    • TMR_CFG_64BIT_WATCHDOG: 看门狗模式

效果: 清零计数器,解除定时器复位

2.2 定时器周期设置

TimerPeriodSet()
 

 
void TimerPeriodSet(
    unsigned int baseAddr,
    unsigned int timer,
    unsigned int period
);

功能: 设置定时器周期值 参数:

  • timer:

    • TMR_TIMER12: 低32位定时器

    • TMR_TIMER34: 高32位定时器

  • period: 周期值 (计数次数)

周期计算:

 

 
定时周期(秒) = period / 时钟频率
示例: 24MHz时钟,1秒周期
period = 24000000

2.3 定时器控制

TimerEnable()
 

 
void TimerEnable(
    unsigned int baseAddr,
    unsigned int timer,
    unsigned int mode
);

功能: 使能定时器 参数:

  • mode:

    • TMR_ENABLE_ONCE: 单次模式

    • TMR_ENABLE_CONT: 连续模式

TimerDisable()
 

 
void TimerDisable(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 禁用定时器

TimerCounterGet()
 

 
unsigned int TimerCounterGet(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 读取当前计数值

TimerReload()
 

 
void TimerReload(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 重新加载周期值

2.4 定时器中断

TimerIntEnable()
 

 
void TimerIntEnable(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 使能定时器中断

TimerIntDisable()
 

 
void TimerIntDisable(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 禁用定时器中断

TimerIntStatusClear()
 

 
void TimerIntStatusClear(
    unsigned int baseAddr,
    unsigned int timer
);

功能: 清除定时器中断标志

2.5 完整应用示例

 

 
/****************************************************************************/
/*                             定时器64位模式完整示例                           */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "timer.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"
#define GPIO_LED_PIN    109    // GPIO6[12]
volatile unsigned int secCount = 0;
/* 中断服务函数 */
void Timer64BitISR(void)
{
    /* 清除定时器中断标志 */
    TimerIntStatusClear(SOC_TMR_0_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
    secCount++;
    /* 每秒翻转LED */
    if(secCount % 2)
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_PIN_HIGH);
    else
        GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_PIN_LOW);
    /* 清除事件标志 */
    IntEventClear(SYS_INT_TIMER64P0_TINT12);
}
int main(void)
{
    /* 使能Timer0模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TMR0, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置GPIO */
    GPIODirModeSet(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_DIR_OUTPUT);
    /* 配置定时器为64位模式 */
    TimerConfigure(SOC_TMR_0_REGS, TMR_CFG_64BIT_CLK_INT);
    /* 设置1秒周期 (24MHz时钟) */
    TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER12, 24000000);
    TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 0);
    /* 使能定时器中断 */
    TimerIntEnable(SOC_TMR_0_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
    /* 配置中断系统 */
    IntDSPINTCInit();
    IntRegister(C674X_MASK_INT4, Timer64BitISR);
    IntEventMap(C674X_MASK_INT4, SYS_INT_TIMER64P0_TINT12);
    IntEnable(C674X_MASK_INT4);
    IntGlobalEnable();
    /* 启动定时器 (连续模式) */
    TimerEnable(SOC_TMR_0_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
    while(1)
    {
        /* 可在此读取计数值 */
        // unsigned int cnt = TimerCounterGet(SOC_TMR_0_REGS, TMR_TIMER12);
    }
}

3. 定时器32位模式

3.1 链式模式 (Chained Mode)

配置:

 

 
TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_32BIT_CH_CLK_INT);

特点:

  • Timer12作为低32位

  • Timer34作为预分频器

  • 级联形成更长的定时周期

周期计算:

 

 
实际周期 = PRD12 × (PRD34 + 1) / 时钟频率

3.2 非链式模式 (Unchained Mode)

配置:

 

 
TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_32BIT_UNCH_CLK_INT);

特点:

  • Timer12和Timer34独立运行

  • 可产生两个独立的定时中断

使用示例:

 

 
// 配置Timer12: 1秒周期
TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER12, 24000000);
TimerEnable(SOC_TMR_1_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
// 配置Timer34: 2秒周期
TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER34, 48000000);
TimerEnable(SOC_TMR_1_REGS, TMR_TIMER34, TMR_ENABLE_CONT);

3.3 完整应用示例

 

 
/****************************************************************************/
/*                          定时器32位非链式模式示例                            */
/*              Timer12产生1秒中断,Timer34产生500ms中断                        */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "timer.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"
#define LED1_PIN    109    // GPIO6[12]
#define LED2_PIN    110    // GPIO6[13]
volatile unsigned int count12 = 0;
volatile unsigned int count34 = 0;
/* Timer12中断服务函数 (1秒) */
void Timer12ISR(void)
{
    TimerIntStatusClear(SOC_TMR_1_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
    count12++;
    /* 翻转LED1 */
    if(count12 % 2)
        GPIOPinWrite(SOC_GPIO_0_REGS, LED1_PIN, GPIO_PIN_HIGH);
    else
        GPIOPinWrite(SOC_GPIO_0_REGS, LED1_PIN, GPIO_PIN_LOW);
    IntEventClear(SYS_INT_TIMER64P1_TINT12);
}
/* Timer34中断服务函数 (500ms) */
void Timer34ISR(void)
{
    TimerIntStatusClear(SOC_TMR_1_REGS, TMR_INT_TMR34_NON_CAPT_MODE);
    count34++;
    /* 翻转LED2 */
    if(count34 % 2)
        GPIOPinWrite(SOC_GPIO_0_REGS, LED2_PIN, GPIO_PIN_HIGH);
    else
        GPIOPinWrite(SOC_GPIO_0_REGS, LED2_PIN, GPIO_PIN_LOW);
    IntEventClear(SYS_INT_TIMER64P1_TINT34);
}
int main(void)
{
    /* 使能Timer1模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TMR1, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置GPIO */
    GPIODirModeSet(SOC_GPIO_0_REGS, LED1_PIN, GPIO_DIR_OUTPUT);
    GPIODirModeSet(SOC_GPIO_0_REGS, LED2_PIN, GPIO_DIR_OUTPUT);
    /* 配置定时器为32位非链式模式 */
    TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_32BIT_UNCH_CLK_INT);
    /* Timer12: 1秒周期 */
    TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER12, 24000000);
    TimerIntEnable(SOC_TMR_1_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
    /* Timer34: 500ms周期 */
    TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER34, 12000000);
    TimerIntEnable(SOC_TMR_1_REGS, TMR_INT_TMR34_NON_CAPT_MODE);
    /* 配置中断 */
    IntDSPINTCInit();
    /* Timer12中断 -> INT4 */
    IntRegister(C674X_MASK_INT4, Timer12ISR);
    IntEventMap(C674X_MASK_INT4, SYS_INT_TIMER64P1_TINT12);
    IntEnable(C674X_MASK_INT4);
    /* Timer34中断 -> INT5 */
    IntRegister(C674X_MASK_INT5, Timer34ISR);
    IntEventMap(C674X_MASK_INT5, SYS_INT_TIMER64P1_TINT34);
    IntEnable(C674X_MASK_INT5);
    IntGlobalEnable();
    /* 启动两个定时器 */
    TimerEnable(SOC_TMR_1_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
    TimerEnable(SOC_TMR_1_REGS, TMR_TIMER34, TMR_ENABLE_CONT);
    while(1);
}

4. UART中断模式

4.1 UART初始化

UARTConfigSetExpClk()
 

 
void UARTConfigSetExpClk(
    unsigned int baseAddr,
    unsigned int baudRate,
    unsigned int wordLength,
    unsigned int stopBits,
    unsigned int parity,
    unsigned int mode
);

功能: 配置UART通信参数 参数:

  • baudRate: 波特率 (如115200)

  • wordLength: 数据位

    • UART_WORDL_5BITS ~ UART_WORDL_8BITS

  • stopBits:

    • UART_FRAME_STB_1: 1个停止位

    • UART_FRAME_STB_2: 2个停止位

  • parity:

    • UART_PARITY_NONE: 无校验

    • UART_PARITY_ODD: 奇校验

    • UART_PARITY_EVEN: 偶校验

  • mode: 工作模式

    • UART_16x_MODE: 16倍过采样

    • UART_13x_MODE: 13倍过采样

4.2 UART中断配置

UARTIntEnable()
 

 
void UARTIntEnable(
    unsigned int baseAddr,
    unsigned int intFlag
);

功能: 使能UART中断 参数:

  • intFlag: 中断类型

    • UART_INT_RXDATA_CTI: 接收超时中断

    • UART_INT_RXDATA: 接收数据中断

    • UART_INT_TXDATA: 发送数据中断

    • UART_INT_LINE: 线路状态中断

UARTFIFOConfig()
 

 
void UARTFIFOConfig(
    unsigned int baseAddr,
    unsigned int fifoConfig,
    unsigned int rxTrigLevel,
    unsigned int txTrigLevel
);

功能: 配置UART FIFO 参数:

  • fifoConfig:

    • UART_FIFO_CONFIG_TXCLR: 清除发送FIFO

    • UART_FIFO_CONFIG_RXCLR: 清除接收FIFO

    • UART_FIFO_CONFIG_DMAMODE1: DMA模式1

  • rxTrigLevel: 接收触发级别 (1/4/8/14字节)

  • txTrigLevel: 发送触发级别

4.3 UART数据收发

UARTCharPut()
 

 
void UARTCharPut(
    unsigned int baseAddr,
    unsigned char data
);

功能: 发送一个字节 (阻塞)

UARTCharPutNonBlocking()
 

 
int UARTCharPutNonBlocking(
    unsigned int baseAddr,
    unsigned char data
);

功能: 发送一个字节 (非阻塞) 返回: 成功返回1,FIFO满返回0

UARTCharGet()
 

 
char UARTCharGet(unsigned int baseAddr);

功能: 接收一个字节 (阻塞)

UARTCharGetNonBlocking()
 

 
int UARTCharGetNonBlocking(unsigned int baseAddr);

功能: 接收一个字节 (非阻塞) 返回: 数据或-1(无数据)

UARTCharsAvail()
 

 
unsigned int UARTCharsAvail(unsigned int baseAddr);

功能: 检查接收FIFO是否有数据 返回: 非零表示有数据

UARTSpaceAvail()
 

 
unsigned int UARTSpaceAvail(unsigned int baseAddr);

功能: 检查发送FIFO是否有空间

4.4 UART中断状态

UARTIntIdentityGet()
 

 
unsigned int UARTIntIdentityGet(unsigned int baseAddr);

功能: 获取中断类型 返回:

  • UART_INTID_RX_DATA: 接收数据中断

  • UART_INTID_TX_EMPTY: 发送空中断

  • UART_INTID_RX_LINE_STAT: 线路状态中断

  • UART_INTID_CHAR_TIMEOUT: 字符超时中断

4.5 完整应用示例

 

 
/****************************************************************************/
/*                           UART中断模式完整示例                              */
/*                        接收数据并回显,支持FIFO                              */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "uart.h"
#include "psc.h"
#include "soc_C6748.h"
#define UART_BASE    SOC_UART_2_REGS
#define BAUD_RATE    115200
/* 接收缓冲区 */
#define RX_BUF_SIZE  256
unsigned char rxBuffer[RX_BUF_SIZE];
volatile unsigned int rxHead = 0;
volatile unsigned int rxTail = 0;
/* UART中断服务函数 */
void UARTIsr(void)
{
    unsigned int intId;
    unsigned char ch;
    /* 获取中断类型 */
    intId = UARTIntIdentityGet(UART_BASE);
    switch(intId)
    {
        case UART_INTID_RX_DATA:      /* 接收数据中断 */
        case UART_INTID_CHAR_TIMEOUT: /* 字符超时中断 */
            /* 读取所有可用数据 */
            while(UARTCharsAvail(UART_BASE))
            {
                ch = UARTCharGetNonBlocking(UART_BASE);
                /* 存入缓冲区 */
                rxBuffer[rxHead] = ch;
                rxHead = (rxHead + 1) % RX_BUF_SIZE;
                /* 回显 */
                UARTCharPut(UART_BASE, ch);
            }
            break;
        case UART_INTID_TX_EMPTY:     /* 发送空中断 */
            /* 发送完成处理 */
            break;
        case UART_INTID_RX_LINE_STAT: /* 线路状态中断 */
            /* 读取LSR清除错误 */
            UARTRxErrorGet(UART_BASE);
            break;
    }
    /* 清除事件标志 */
    IntEventClear(SYS_INT_UART2_INT);
}
void UARTInit(void)
{
    /* 使能UART2模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART2, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置UART参数: 115200, 8N1 */
    UARTConfigSetExpClk(UART_BASE,
                        SOC_UART_2_MODULE_FREQ,
                        BAUD_RATE,
                        UART_WORDL_8BITS,
                        UART_FRAME_STB_1,
                        UART_PARITY_NONE,
                        UART_16x_MODE);
    /* 配置FIFO: 使能FIFO,接收触发级别8字节 */
    UARTFIFOConfig(UART_BASE,
                   UART_FIFO_CONFIG_TXCLR | UART_FIFO_CONFIG_RXCLR,
                   UART_RX_TRIG_LEVEL_8,
                   UART_TX_TRIG_LEVEL_1);
    /* 使能接收中断和接收超时中断 */
    UARTIntEnable(UART_BASE, UART_INT_RXDATA_CTI);
}
void InterruptInit(void)
{
    IntDSPINTCInit();
    /* 注册UART2中断 */
    IntRegister(C674X_MASK_INT4, UARTIsr);
    IntEventMap(C674X_MASK_INT4, SYS_INT_UART2_INT);
    IntEnable(C674X_MASK_INT4);
    IntGlobalEnable();
}
int main(void)
{
    UARTInit();
    InterruptInit();
    /* 发送欢迎信息 */
    UARTCharPut(UART_BASE, 'R');
    UARTCharPut(UART_BASE, 'e');
    UARTCharPut(UART_BASE, 'a');
    UARTCharPut(UART_BASE, 'd');
    UARTCharPut(UART_BASE, 'y');
    UARTCharPut(UART_BASE, '\r');
    UARTCharPut(UART_BASE, '\n');
    while(1)
    {
        /* 处理接收数据 */
        while(rxHead != rxTail)
        {
            unsigned char data = rxBuffer[rxTail];
            rxTail = (rxTail + 1) % RX_BUF_SIZE;
            /* 在此处理接收到的数据 */
        }
    }
}

5. UART轮询模式

5.1 初始化函数

UARTStdioInit()
 

 
void UARTStdioInit(void);

功能: 初始化UART标准输入输出 (默认UART2, 115200波特率)

内部实现:

 

 
void UARTStdioInit(void) {
    UARTConfigSetExpClk(UART_CONSOLE_BASE,
                        SOC_UART_2_REGS,
                        115200,
                        UART_WORDL_8BITS,
                        UART_FRAME_STB_1,
                        UART_PARITY_NONE,
                        UART_16x_MODE);
}

5.2 轮询发送函数

UARTPutc()
 

 
void UARTPutc(unsigned char data);

功能: 发送单个字符 (轮询方式)

UARTPuts()
 

 
void UARTPuts(const char *str, int length);

功能: 发送字符串 参数:

  • str: 字符串指针

  • length:

    • > 0: 发送指定长度

    • < 0: 发送到'\0'结束

    • = 0: 不发送

UARTprintf()
 

 
void UARTprintf(const char *format, ...);

功能: 格式化输出 支持格式:

  • %c: 字符

  • %d, %i: 十进制整数

  • %u: 无符号十进制

  • %x, %X: 十六进制

  • %s: 字符串

  • %p: 指针

  • %%: 百分号

示例:

 

 
UARTprintf("Value: %d, Hex: 0x%X\n", 100, 0xFF);

5.3 轮询接收函数

UARTGetc()
 

 
unsigned char UARTGetc(void);

功能: 接收单个字符 (轮询阻塞)

UARTGets()
 

 
int UARTGets(char *buffer, int length);

功能: 接收字符串 (直到回车或达到长度限制) 返回: 接收的字符数

5.4 完整应用示例

 

 
/****************************************************************************/
/*                           UART轮询模式完整示例                              */
/****************************************************************************/
#include "TMS320C6748.h"
#include "uartStdio.h"
#include "psc.h"
#include "soc_C6748.h"
int main(void)
{
    char buffer[64];
    int value = 12345;
    /* 使能UART2模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART2, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 初始化UART标准IO (UART2, 115200) */
    UARTStdioInit();
    /* 使用UARTprintf格式化输出 */
    UARTprintf("TMS320C6748 UART Demo\r\n");
    UARTprintf("Value: %d, Hex: 0x%X\r\n", value, value);
    /* 使用UARTPuts发送字符串 */
    UARTPuts("Enter your name: ", -1);
    /* 使用UARTGets接收字符串 */
    UARTGets(buffer, sizeof(buffer));
    /* 回显输入 */
    UARTprintf("\r\nHello, %s!\r\n", buffer);
    /* 单字符收发示例 */
    UARTPuts("Press any key: ", -1);
    char ch = UARTGetc();      /* 阻塞等待输入 */
    UARTprintf("\r\nYou pressed: %c (0x%02X)\r\n", ch, ch);
    while(1)
    {
        /* 简单回显 */
        ch = UARTGetc();
        UARTPutc(ch);
    }
}

6. EDMA+GPIO中断

6.1 EDMA初始化

EDMA3Init()
 

 
void EDMA3Init(
    unsigned int baseAddr,
    unsigned int queNum
);

功能: 初始化EDMA3模块 参数:

  • baseAddr: EDMA3_CC基地址

  • queNum: 队列号 (0-1)

EDMA3RequestChannel()
 

 
unsigned int EDMA3RequestChannel(
    unsigned int baseAddr,
    unsigned int chType,
    unsigned int chNum,
    unsigned int tccNum,
    unsigned int evtQNum
);

功能: 请求EDMA通道 参数:

  • chType: 通道类型

    • EDMA3_CHANNEL_TYPE_DMA: DMA通道

    • EDMA3_CHANNEL_TYPE_QDMA: QDMA通道

  • chNum: 通道号 (0-63)

  • tccNum: TCC号 (传输完成码)

  • evtQNum: 事件队列号

返回: 成功返回TRUE

6.2 PaRAM配置

EDMA3SetPaRAM()
 

 
void EDMA3SetPaRAM(
    unsigned int baseAddr,
    unsigned int chNum,
    EDMA3CCPaRAMEntry *paramEntry
);

功能: 设置PaRAM参数 参数:

  • paramEntry: PaRAM结构体指针

EDMA3CCPaRAMEntry结构:

 

 
typedef struct {
    unsigned int opt;        // 选项参数
    unsigned int srcAddr;    // 源地址
    unsigned short aCnt;     // A维度计数
    unsigned short bCnt;     // B维度计数
    unsigned int dstAddr;    // 目标地址
    short srcBIdx;           // 源B索引
    short dstBIdx;           // 目标B索引
    unsigned short linkAddr; // 链接地址
    unsigned short bCntReload;
    short srcCIdx;           // 源C索引
    short dstCIdx;           // 目标C索引
    unsigned short cCnt;     // C维度计数
} EDMA3CCPaRAMEntry;
EDMA3GetPaRAM()
 

 
void EDMA3GetPaRAM(
    unsigned int baseAddr,
    unsigned int chNum,
    EDMA3CCPaRAMEntry *paramEntry
);

功能: 读取PaRAM参数

6.3 EDMA通道控制

EDMA3EnableTransfer()
 

 
void EDMA3EnableTransfer(
    unsigned int baseAddr,
    unsigned int chNum,
    unsigned int trigMode
);

功能: 使能EDMA传输 参数:

  • trigMode:

    • EDMA3_TRIG_MODE_MANUAL: 手动触发

    • EDMA3_TRIG_MODE_EVENT: 事件触发

EDMA3DisableTransfer()
 

 
void EDMA3DisableTransfer(
    unsigned int baseAddr,
    unsigned int chNum,
    unsigned int trigMode
);

功能: 禁用EDMA传输

EDMA3ChannelToParamMap()
 

 
void EDMA3ChannelToParamMap(
    unsigned int baseAddr,
    unsigned int chType,
    unsigned int chNum,
    unsigned int paramId
);

功能: 映射通道到PaRAM集

6.4 EDMA中断

EDMA3EnableChInShadowReg()
 

 
void EDMA3EnableChInShadowReg(
    unsigned int baseAddr,
    unsigned int shadowNum,
    unsigned int chNum
);

功能: 在影子区域使能通道

EDMA3ClrIntr()
 

 
void EDMA3ClrIntr(
    unsigned int baseAddr,
    unsigned int tccNum
);

功能: 清除EDMA中断标志 参数:

  • tccNum: TCC号 (0-63)

EDMA3GetIntrStatus()
 

 
unsigned int EDMA3GetIntrStatus(
    unsigned int baseAddr
);

功能: 获取中断状态寄存器值

6.5 完整应用示例

 

 
/****************************************************************************/
/*                        EDMA+GPIO中断完整示例                               */
/*                   EDMA内存传输+传输完成中断处理                              */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "edma.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"
#define EDMA_BASE       SOC_EDMA3_CC_0_REGS
#define DMA_CHANNEL     0       /* 使用DMA通道0 */
#define TCC_NUM         0       /* TCC号 */
#define EVT_QUEUE       0       /* 事件队列0 */
#define BUFFER_SIZE     256
#define GPIO_LED_PIN    109     /* GPIO6[12] */
/* 源和目标缓冲区 */
#pragma DATA_ALIGN(srcBuffer, 8)
unsigned char srcBuffer[BUFFER_SIZE];
#pragma DATA_ALIGN(dstBuffer, 8)
unsigned char dstBuffer[BUFFER_SIZE];
volatile unsigned int transferComplete = 0;
/* EDMA中断服务函数 */
void EDMA3Isr(void)
{
    unsigned int intrStatus;
    /* 获取中断状态 */
    intrStatus = EDMA3GetIntrStatus(EDMA_BASE);
    /* 检查TCC0中断 */
    if(intrStatus & (1 << TCC_NUM))
    {
        /* 清除中断标志 */
        EDMA3ClrIntr(EDMA_BASE, TCC_NUM);
        /* 设置传输完成标志 */
        transferComplete = 1;
        /* LED翻转指示 */
        if(GPIOPinRead(SOC_GPIO_0_REGS, GPIO_LED_PIN))
            GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_PIN_LOW);
        else
            GPIOPinWrite(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_PIN_HIGH);
    }
    IntEventClear(SYS_INT_EDMA3_CC0_INT1);
}
void EDMAInit(void)
{
    EDMA3CCPaRAMEntry paramSet;
    /* 使能EDMA3模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 初始化EDMA3 */
    EDMA3Init(EDMA_BASE, EVT_QUEUE);
    /* 请求DMA通道 */
    EDMA3RequestChannel(EDMA_BASE, EDMA3_CHANNEL_TYPE_DMA, DMA_CHANNEL,
                        TCC_NUM, EVT_QUEUE);
    /* 配置PaRAM */
    paramSet.opt = 0;
    paramSet.opt |= (TCC_NUM << 12);        /* TCC号 */
    paramSet.opt |= (1 << 20);              /* TCINTEN: 传输完成中断使能 */
    paramSet.srcAddr = (unsigned int)srcBuffer;
    paramSet.destAddr = (unsigned int)dstBuffer;
    paramSet.aCnt = BUFFER_SIZE;
    paramSet.bCnt = 1;
    paramSet.cCnt = 1;
    paramSet.srcBIdx = 0;
    paramSet.destBIdx = 0;
    paramSet.srcCIdx = 0;
    paramSet.destCIdx = 0;
    paramSet.linkAddr = 0xFFFF;             /* 无链接 */
    paramSet.bCntReload = 0;
    /* 设置PaRAM */
    EDMA3SetPaRAM(EDMA_BASE, DMA_CHANNEL, &paramSet);
}
void InterruptInit(void)
{
    IntDSPINTCInit();
    /* 注册EDMA中断 */
    IntRegister(C674X_MASK_INT4, EDMA3Isr);
    IntEventMap(C674X_MASK_INT4, SYS_INT_EDMA3_CC0_INT1);
    IntEnable(C674X_MASK_INT4);
    IntGlobalEnable();
}
int main(void)
{
    unsigned int i;
    /* 使能GPIO */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    GPIODirModeSet(SOC_GPIO_0_REGS, GPIO_LED_PIN, GPIO_DIR_OUTPUT);
    /* 初始化源缓冲区 */
    for(i = 0; i < BUFFER_SIZE; i++)
    {
        srcBuffer[i] = i;
        dstBuffer[i] = 0;
    }
    EDMAInit();
    InterruptInit();
    /* 触发EDMA传输 */
    transferComplete = 0;
    EDMA3EnableTransfer(EDMA_BASE, DMA_CHANNEL, EDMA3_TRIG_MODE_MANUAL);
    /* 等待传输完成 */
    while(!transferComplete);
    /* 验证数据 */
    for(i = 0; i < BUFFER_SIZE; i++)
    {
        if(dstBuffer[i] != srcBuffer[i])
        {
            /* 数据错误 */
            while(1);
        }
    }
    /* 测试通过 */
    while(1);
}

7. RS485通信

7.1 RS485配置

RS485使用UART硬件 + GPIO控制方向:

 

 
// 发送模式
GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_HIGH);
UARTCharPut(UART_BASE, data);
// 接收模式
GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_LOW);
data = UARTCharGet(UART_BASE);

7.2 方向控制宏定义

 

 
#define RS485_TX_ENABLE()   GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_HIGH)
#define RS485_RX_ENABLE()   GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_LOW)

7.3 RS485发送函数

 

 
void RS485SendByte(unsigned char data) {
    RS485_TX_ENABLE();
    UARTCharPut(UART_BASE, data);
    while(!UARTSpaceAvail(UART_BASE));  // 等待发送完成
    RS485_RX_ENABLE();
}
void RS485SendString(const char *str, int len) {
    RS485_TX_ENABLE();
    for(int i = 0; i < len; i++) {
        UARTCharPut(UART_BASE, str[i]);
    }
    while(!UARTSpaceAvail(UART_BASE));
    RS485_RX_ENABLE();
}

7.4 RS485接收函数

 

 
unsigned char RS485ReceiveByte(void) {
    RS485_RX_ENABLE();
    return UARTCharGet(UART_BASE);
}

7.5 完整应用示例

 

 
/****************************************************************************/
/*                           RS485通信完整示例                                */
/*                    半双工通信,GPIO控制收发方向                              */
/****************************************************************************/
#include "TMS320C6748.h"
#include "uart.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"
#define UART_BASE       SOC_UART_1_REGS
#define RS485_DE_PIN    108    /* GPIO6[11] - 方向控制引脚 */
#define BAUD_RATE       9600
/* 方向控制宏 */
#define RS485_TX_ENABLE()   GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_HIGH)
#define RS485_RX_ENABLE()   GPIOPinWrite(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_PIN_LOW)
/* 延时函数 (等待发送完成) */
void Delay(unsigned int count)
{
    while(count--);
}
/* RS485发送单字节 */
void RS485SendByte(unsigned char data)
{
    RS485_TX_ENABLE();
    UARTCharPut(UART_BASE, data);
    /* 等待发送完成 */
    while(!(UARTSpaceAvail(UART_BASE)));
    Delay(100);  /* 等待最后一位发送完成 */
    RS485_RX_ENABLE();
}
/* RS485发送字符串 */
void RS485SendString(const char *str, int len)
{
    int i;
    RS485_TX_ENABLE();
    for(i = 0; i < len; i++)
    {
        UARTCharPut(UART_BASE, str[i]);
    }
    /* 等待所有数据发送完成 */
    while(!(UARTSpaceAvail(UART_BASE)));
    Delay(100);
    RS485_RX_ENABLE();
}
/* RS485接收单字节 (阻塞) */
unsigned char RS485ReceiveByte(void)
{
    RS485_RX_ENABLE();
    return UARTCharGet(UART_BASE);
}
/* RS485接收单字节 (非阻塞) */
int RS485ReceiveByteNonBlocking(unsigned char *data)
{
    RS485_RX_ENABLE();
    if(UARTCharsAvail(UART_BASE))
    {
        *data = UARTCharGetNonBlocking(UART_BASE);
        return 1;
    }
    return 0;
}
void RS485Init(void)
{
    /* 使能UART1和GPIO模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART1, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置方向控制引脚为输出 */
    GPIODirModeSet(SOC_GPIO_0_REGS, RS485_DE_PIN, GPIO_DIR_OUTPUT);
    /* 默认接收模式 */
    RS485_RX_ENABLE();
    /* 配置UART: 9600, 8N1 */
    UARTConfigSetExpClk(UART_BASE,
                        SOC_UART_1_MODULE_FREQ,
                        BAUD_RATE,
                        UART_WORDL_8BITS,
                        UART_FRAME_STB_1,
                        UART_PARITY_NONE,
                        UART_16x_MODE);
}
int main(void)
{
    unsigned char rxData;
    char txMsg[] = "Hello RS485!";
    RS485Init();
    /* 发送测试消息 */
    RS485SendString(txMsg, sizeof(txMsg) - 1);
    while(1)
    {
        /* 接收数据并回显 */
        if(RS485ReceiveByteNonBlocking(&rxData))
        {
            RS485SendByte(rxData);
        }
    }
}

8. I2C与EEPROM

8.1 I2C主机初始化

I2CMasterInitExpClk()
 

 
void I2CMasterInitExpClk(
    unsigned int baseAddr,
    unsigned int sysClk,
    unsigned int internalClk,
    unsigned int outputClk
);

功能: 初始化I2C主机模式 参数:

  • sysClk: 系统时钟频率 (Hz)

  • internalClk: I2C模块内部时钟 (通常8-12MHz)

  • outputClk: SCL输出时钟频率 (如100kHz/400kHz)

示例:

 

 
I2CMasterInitExpClk(SOC_I2C_0_REGS,
                    150000000,    // 系统时钟150MHz
                    10000000,     // 内部时钟10MHz
                    100000);      // SCL 100kHz

8.2 I2C基本控制

I2CMasterEnable()
 

 
void I2CMasterEnable(unsigned int baseAddr);

功能: 使能I2C主机模式

I2CMasterDisable()
 

 
void I2CMasterDisable(unsigned int baseAddr);

功能: 禁用I2C主机模式

I2CSetSlaveAdd()
 

 
void I2CSetSlaveAdd(
    unsigned int baseAddr,
    unsigned int slaveAdd
);

功能: 设置从机地址 参数:

  • slaveAdd: 7位从机地址

8.3 I2C数据传输

I2CMasterDataPut()
 

 
void I2CMasterDataPut(
    unsigned int baseAddr,
    unsigned char data
);

功能: 写入要发送的数据

I2CMasterDataGet()
 

 
unsigned char I2CMasterDataGet(unsigned int baseAddr);

功能: 读取接收的数据

I2CMasterControl()
 

 
void I2CMasterControl(
    unsigned int baseAddr,
    unsigned int cmd
);

功能: 控制I2C传输 参数:

  • cmd: 控制命令

    • I2C_MASTER_CMD_START: 发送START条件

    • I2C_MASTER_CMD_STOP: 发送STOP条件

    • I2C_MASTER_CMD_RSTART: 发送重复START

    • I2C_MASTER_CMD_SINGLE_SEND: 单字节发送

    • I2C_MASTER_CMD_SINGLE_RECEIVE: 单字节接收

    • I2C_MASTER_CMD_BURST_SEND_START: 突发发送开始

    • I2C_MASTER_CMD_BURST_SEND_CONT: 突发发送继续

    • I2C_MASTER_CMD_BURST_SEND_FINISH: 突发发送结束

8.4 I2C状态检查

I2CMasterBusy()
 

 
unsigned int I2CMasterBusy(unsigned int baseAddr);

功能: 检查I2C是否忙 返回: 非零表示忙

I2CMasterBusBusy()
 

 
unsigned int I2CMasterBusBusy(unsigned int baseAddr);

功能: 检查I2C总线是否忙

I2CMasterErr()
 

 
unsigned int I2CMasterErr(unsigned int baseAddr);

功能: 获取I2C错误状态 返回:

  • I2C_MASTER_ERR_NONE: 无错误

  • I2C_MASTER_ERR_ADDR_ACK: 地址应答错误

  • I2C_MASTER_ERR_DATA_ACK: 数据应答错误

  • I2C_MASTER_ERR_ARB_LOST: 仲裁丢失

8.5 EEPROM操作函数

EEPROMByteWrite()
 

 
void EEPROMByteWrite(
    unsigned int baseAddr,
    unsigned int slaveAddr,
    unsigned int memAddr,
    unsigned char data
);

功能: 写入单字节到EEPROM 参数:

  • slaveAddr: EEPROM地址 (如0x50)

  • memAddr: 存储器地址

  • data: 要写入的数据

EEPROMCurrentAddressRead()
 

 
unsigned char EEPROMCurrentAddressRead(
    unsigned int baseAddr,
    unsigned int slaveAddr
);

功能: 从当前地址读取

EEPROMRandomRead()
 

 
unsigned char EEPROMRandomRead(
    unsigned int baseAddr,
    unsigned int slaveAddr,
    unsigned int memAddr
);

功能: 随机读取单字节

EEPROMPageWrite()
 

 
void EEPROMPageWrite(
    unsigned int baseAddr,
    unsigned int slaveAddr,
    unsigned int memAddr,
    unsigned char *data,
    unsigned int length
);

功能: 页写入 (最多8/16/32字节) 注意: 写入后需延时5ms等待内部写周期完成

EEPROMSequentialRead()
 

 
void EEPROMSequentialRead(
    unsigned int baseAddr,
    unsigned int slaveAddr,
    unsigned int memAddr,
    unsigned char *buffer,
    unsigned int length
);

功能: 连续读取多字节

8.6 完整应用示例

 

 
/****************************************************************************/
/*                        I2C与EEPROM读写完整示例                              */
/*                      AT24C02 EEPROM (256字节)                              */
/****************************************************************************/
#include "TMS320C6748.h"
#include "i2c.h"
#include "psc.h"
#include "soc_C6748.h"
#define I2C_BASE        SOC_I2C_0_REGS
#define EEPROM_ADDR     0x50        /* EEPROM从机地址 */
#define SYS_CLK         150000000   /* 系统时钟150MHz */
#define I2C_INT_CLK     10000000    /* I2C内部时钟10MHz */
#define I2C_OUT_CLK     100000      /* I2C输出时钟100kHz */
/* 延时函数 (EEPROM写周期需要5ms) */
void DelayMs(unsigned int ms)
{
    volatile unsigned int i;
    for(; ms > 0; ms--)
        for(i = 0; i < 10000; i++);
}
/* I2C等待总线空闲 */
void I2CWaitBusFree(void)
{
    while(I2CMasterBusBusy(I2C_BASE));
}
/* I2C等待传输完成 */
void I2CWaitComplete(void)
{
    while(I2CMasterBusy(I2C_BASE));
}
/* EEPROM单字节写入 */
void EEPROMByteWrite(unsigned int memAddr, unsigned char data)
{
    I2CWaitBusFree();
    /* 设置从机地址 */
    I2CSetSlaveAdd(I2C_BASE, EEPROM_ADDR);
    /* 设置数据计数 (地址+数据=2字节) */
    I2CSetDataCount(I2C_BASE, 2);
    /* 配置为主机发送模式并启动 */
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_TX | I2C_CFG_START | I2C_CFG_STOP);
    /* 发送存储器地址 */
    I2CMasterDataPut(I2C_BASE, memAddr);
    I2CWaitComplete();
    /* 发送数据 */
    I2CMasterDataPut(I2C_BASE, data);
    I2CWaitComplete();
    /* 等待EEPROM内部写周期完成 */
    DelayMs(5);
}
/* EEPROM单字节读取 */
unsigned char EEPROMRandomRead(unsigned int memAddr)
{
    unsigned char data;
    I2CWaitBusFree();
    /* 第一步: 发送存储器地址 (Dummy Write) */
    I2CSetSlaveAdd(I2C_BASE, EEPROM_ADDR);
    I2CSetDataCount(I2C_BASE, 1);
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_TX | I2C_CFG_START);
    I2CMasterDataPut(I2C_BASE, memAddr);
    I2CWaitComplete();
    /* 第二步: 重复起始并读取数据 */
    I2CSetDataCount(I2C_BASE, 1);
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_RX | I2C_CFG_START | I2C_CFG_STOP);
    I2CWaitComplete();
    data = I2CMasterDataGet(I2C_BASE);
    return data;
}
/* EEPROM页写入 (AT24C02最多8字节/页) */
void EEPROMPageWrite(unsigned int memAddr, unsigned char *data, unsigned int len)
{
    unsigned int i;
    I2CWaitBusFree();
    I2CSetSlaveAdd(I2C_BASE, EEPROM_ADDR);
    I2CSetDataCount(I2C_BASE, len + 1);  /* 地址 + 数据 */
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_TX | I2C_CFG_START | I2C_CFG_STOP);
    /* 发送存储器地址 */
    I2CMasterDataPut(I2C_BASE, memAddr);
    I2CWaitComplete();
    /* 发送数据 */
    for(i = 0; i < len; i++)
    {
        I2CMasterDataPut(I2C_BASE, data[i]);
        I2CWaitComplete();
    }
    /* 等待EEPROM内部写周期完成 */
    DelayMs(5);
}
/* EEPROM连续读取 */
void EEPROMSequentialRead(unsigned int memAddr, unsigned char *buffer, unsigned int len)
{
    unsigned int i;
    I2CWaitBusFree();
    /* 发送存储器地址 */
    I2CSetSlaveAdd(I2C_BASE, EEPROM_ADDR);
    I2CSetDataCount(I2C_BASE, 1);
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_TX | I2C_CFG_START);
    I2CMasterDataPut(I2C_BASE, memAddr);
    I2CWaitComplete();
    /* 连续读取 */
    I2CSetDataCount(I2C_BASE, len);
    I2CMasterControl(I2C_BASE, I2C_CFG_MST_RX | I2C_CFG_START | I2C_CFG_STOP);
    for(i = 0; i < len; i++)
    {
        I2CWaitComplete();
        buffer[i] = I2CMasterDataGet(I2C_BASE);
    }
}
void I2CInit(void)
{
    /* 使能I2C0模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_I2C0, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 初始化I2C: 100kHz */
    I2CMasterInitExpClk(I2C_BASE, SYS_CLK, I2C_INT_CLK, I2C_OUT_CLK);
    /* 使能I2C主机模式 */
    I2CMasterEnable(I2C_BASE);
}
int main(void)
{
    unsigned char writeBuf[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
    unsigned char readBuf[8];
    unsigned int i;
    I2CInit();
    /* 单字节写入测试 */
    EEPROMByteWrite(0x00, 0xAA);
    /* 单字节读取测试 */
    unsigned char data = EEPROMRandomRead(0x00);
    /* 页写入测试 (地址0x10开始) */
    EEPROMPageWrite(0x10, writeBuf, 8);
    /* 连续读取测试 */
    EEPROMSequentialRead(0x10, readBuf, 8);
    /* 验证数据 */
    for(i = 0; i < 8; i++)
    {
        if(readBuf[i] != writeBuf[i])
        {
            /* 数据错误 */
            while(1);
        }
    }
    /* 测试通过 */
    while(1);
}

9. EDMA+SPI Flash

9.1 SPI初始化

SPIReset()
 

 
void SPIReset(unsigned int baseAddr);

功能: 复位SPI模块

SPIOutOfReset()
 

 
void SPIOutOfReset(unsigned int baseAddr);

功能: 使SPI退出复位状态

SPIModeConfigure()
 

 
void SPIModeConfigure(
    unsigned int baseAddr,
    unsigned int mode
);

功能: 配置SPI主从模式 参数:

  • mode:

    • SPI_MASTER_MODE: 主机模式

    • SPI_SLAVE_MODE: 从机模式

SPIClkConfigure()
 

 
void SPIClkConfigure(
    unsigned int baseAddr,
    unsigned int spiClk,
    unsigned int spiDataRate,
    unsigned int format
);

功能: 配置SPI时钟 参数:

  • spiClk: SPI模块输入时钟

  • spiDataRate: 目标数据速率

  • format: 时钟格式

    • SPI_DATA_FORMAT0: CPOL=0, CPHA=0

    • SPI_DATA_FORMAT1: CPOL=0, CPHA=1

    • SPI_DATA_FORMAT2: CPOL=1, CPHA=0

    • SPI_DATA_FORMAT3: CPOL=1, CPHA=1

9.2 SPI片选控制

SPIPinControl()
 

 
void SPIPinControl(
    unsigned int baseAddr,
    unsigned int csNum,
    unsigned int ctrl
);

功能: 控制SPI引脚功能 参数:

  • csNum: 片选号 (0-7)

  • ctrl:

    • SPI_PIN_CS_ENABLE: 使能为片选

    • SPI_PIN_CS_DISABLE: 禁用片选功能

SPIDefaultCSSet()
 

 
void SPIDefaultCSSet(
    unsigned int baseAddr,
    unsigned int csNum
);

功能: 设置默认片选

9.3 SPI数据传输

SPITransmitData()
 

 
void SPITransmitData(
    unsigned int baseAddr,
    unsigned int data,
    unsigned int dataLen
);

功能: 发送数据 (轮询方式) 参数:

  • data: 要发送的数据

  • dataLen: 数据长度

    • SPI_DATA_LENGTH_8: 8位

    • SPI_DATA_LENGTH_16: 16位

SPIReceiveData()
 

 
unsigned int SPIReceiveData(
    unsigned int baseAddr,
    unsigned int dataLen
);

功能: 接收数据 (轮询方式)

9.4 SPI DMA配置

SPIDMAEnable()
 

 
void SPIDMAEnable(
    unsigned int baseAddr,
    unsigned int flag
);

功能: 使能SPI DMA 参数:

  • flag:

    • SPI_DMA_REQUEST_TX: 发送DMA

    • SPI_DMA_REQUEST_RX: 接收DMA

SPITxEdmaParamSet()
 

 
void SPITxEdmaParamSet(
    EDMA3CCPaRAMEntry *paramEntry,
    unsigned int srcAddr,
    unsigned int destAddr,
    unsigned int aCnt,
    unsigned int bCnt,
    unsigned int cCnt
);

功能: 配置SPI发送EDMA参数

SPIRxEdmaParamSet()
 

 
void SPIRxEdmaParamSet(
    EDMA3CCPaRAMEntry *paramEntry,
    unsigned int srcAddr,
    unsigned int destAddr,
    unsigned int aCnt,
    unsigned int bCnt,
    unsigned int cCnt
);

功能: 配置SPI接收EDMA参数

9.5 Flash操作函数

FlashWriteEnable()
 

 
void FlashWriteEnable(void);

功能: 使能Flash写操作

FlashStatusRegRead()
 

 
unsigned char FlashStatusRegRead(void);

功能: 读取Flash状态寄存器

FlashReadID()
 

 
unsigned int FlashReadID(void);

功能: 读取Flash ID

FlashPageWrite()
 

 
void FlashPageWrite(
    unsigned int addr,
    unsigned char *buffer,
    unsigned int length
);

功能: 页编程 (最多256字节)

FlashRead()
 

 
void FlashRead(
    unsigned int addr,
    unsigned char *buffer,
    unsigned int length
);

功能: 读取Flash数据

FlashSectorErase()
 

 
void FlashSectorErase(unsigned int addr);

功能: 擦除扇区 (4KB)

FlashBlockErase()
 

 
void FlashBlockErase(unsigned int addr);

功能: 擦除块 (64KB)

FlashChipErase()
 

 
void FlashChipErase(void);

功能: 全片擦除

9.6 完整应用示例

 

 
/****************************************************************************/
/*                        SPI Flash读写完整示例                               */
/*                     W25Q16 SPI Flash (2MB)                                */
/****************************************************************************/
#include "TMS320C6748.h"
#include "spi.h"
#include "psc.h"
#include "soc_C6748.h"
#define SPI_BASE        SOC_SPI_1_REGS
#define SPI_CLK         150000000   /* SPI模块时钟 */
#define SPI_DATA_RATE   10000000    /* SPI数据速率10MHz */
#define CS_NUM          0           /* 片选号 */
/* Flash命令 */
#define CMD_WRITE_ENABLE    0x06
#define CMD_WRITE_DISABLE   0x04
#define CMD_READ_STATUS     0x05
#define CMD_READ_DATA       0x03
#define CMD_PAGE_PROGRAM    0x02
#define CMD_SECTOR_ERASE    0x20
#define CMD_BLOCK_ERASE     0xD8
#define CMD_CHIP_ERASE      0xC7
#define CMD_READ_ID         0x9F
/* SPI发送并接收一个字节 */
unsigned char SPITransfer(unsigned char data)
{
    SPITransmitData(SPI_BASE, data, SPI_DATA_LENGTH_8);
    while(!SPIIntStatus(SPI_BASE, SPI_INT_RX_FULL));
    return SPIReceiveData(SPI_BASE, SPI_DATA_LENGTH_8);
}
/* Flash写使能 */
void FlashWriteEnable(void)
{
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_WRITE_ENABLE);
}
/* 读取Flash状态寄存器 */
unsigned char FlashReadStatus(void)
{
    unsigned char status;
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_READ_STATUS);
    status = SPITransfer(0xFF);
    return status;
}
/* 等待Flash空闲 */
void FlashWaitBusy(void)
{
    while(FlashReadStatus() & 0x01);
}
/* 读取Flash ID */
unsigned int FlashReadID(void)
{
    unsigned int id;
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_READ_ID);
    id = SPITransfer(0xFF) << 16;
    id |= SPITransfer(0xFF) << 8;
    id |= SPITransfer(0xFF);
    return id;
}
/* 读取Flash数据 */
void FlashRead(unsigned int addr, unsigned char *buffer, unsigned int len)
{
    unsigned int i;
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_READ_DATA);
    SPITransfer((addr >> 16) & 0xFF);
    SPITransfer((addr >> 8) & 0xFF);
    SPITransfer(addr & 0xFF);
    for(i = 0; i < len; i++)
    {
        buffer[i] = SPITransfer(0xFF);
    }
}
/* 页编程 (最多256字节) */
void FlashPageProgram(unsigned int addr, unsigned char *data, unsigned int len)
{
    unsigned int i;
    FlashWriteEnable();
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_PAGE_PROGRAM);
    SPITransfer((addr >> 16) & 0xFF);
    SPITransfer((addr >> 8) & 0xFF);
    SPITransfer(addr & 0xFF);
    for(i = 0; i < len; i++)
    {
        SPITransfer(data[i]);
    }
    FlashWaitBusy();
}
/* 扇区擦除 (4KB) */
void FlashSectorErase(unsigned int addr)
{
    FlashWriteEnable();
    SPIDat1Config(SPI_BASE, SPI_DATA_FORMAT0, CS_NUM);
    SPITransfer(CMD_SECTOR_ERASE);
    SPITransfer((addr >> 16) & 0xFF);
    SPITransfer((addr >> 8) & 0xFF);
    SPITransfer(addr & 0xFF);
    FlashWaitBusy();
}
void SPIInit(void)
{
    /* 使能SPI1模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_SPI1, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 复位SPI */
    SPIReset(SPI_BASE);
    SPIOutOfReset(SPI_BASE);
    /* 配置SPI主机模式 */
    SPIModeConfigure(SPI_BASE, SPI_MASTER_MODE);
    /* 配置SPI时钟: CPOL=0, CPHA=0 */
    SPIClkConfigure(SPI_BASE, SPI_CLK, SPI_DATA_RATE, SPI_DATA_FORMAT0);
    /* 使能片选功能 */
    SPIPinControl(SPI_BASE, CS_NUM, SPI_PIN_CS_ENABLE);
    /* 配置数据格式: 8位 */
    SPIDataFormatConfig(SPI_BASE, SPI_DATA_FORMAT0, 8);
    /* 使能SPI */
    SPIEnable(SPI_BASE);
}
int main(void)
{
    unsigned char writeBuf[256];
    unsigned char readBuf[256];
    unsigned int flashId;
    unsigned int i;
    SPIInit();
    /* 读取Flash ID */
    flashId = FlashReadID();  /* W25Q16应返回0xEF4015 */
    /* 初始化测试数据 */
    for(i = 0; i < 256; i++)
        writeBuf[i] = i;
    /* 擦除第一个扇区 */
    FlashSectorErase(0x000000);
    /* 写入数据 */
    FlashPageProgram(0x000000, writeBuf, 256);
    /* 读取数据 */
    FlashRead(0x000000, readBuf, 256);
    /* 验证数据 */
    for(i = 0; i < 256; i++)
    {
        if(readBuf[i] != writeBuf[i])
        {
            /* 数据错误 */
            while(1);
        }
    }
    /* 测试通过 */
    while(1);
}

10. PWM(eHRPWM)模块

10.1 PWM基本配置

PWMTBClkSyncEnable()
 

 
void PWMTBClkSyncEnable(unsigned int baseAddr);

功能: 使能时基时钟同步

PWMClkDiv()
 

 
void PWMClkDiv(
    unsigned int baseAddr,
    unsigned int tbClk,
    unsigned int pwmClk
);

功能: 配置PWM时钟分频 参数:

  • tbClk: 时基时钟分频 (TBCLKDIV)

    • PWM_TB_CLK_DIV_1 ~ PWM_TB_CLK_DIV_128

  • pwmClk: 高速时钟分频 (HSPCLKDIV)

    • PWM_HS_CLK_DIV_1 ~ `PWM_HS_CLK_DIV_14`

计算公式:

 

 
TBCLK = SYSCLK / (HSPCLKDIV × TBCLKDIV)
PWMTimeBaseConfig()
 

 
void PWMTimeBaseConfig(
    unsigned int baseAddr,
    unsigned int direction,
    unsigned int syncOut
);

功能: 配置时基 参数:

  • direction: 计数方向

    • PWM_TB_COUNT_UP: 向上计数

    • PWM_TB_COUNT_DOWN: 向下计数

    • PWM_TB_COUNT_UPDOWN: 增减计数

  • syncOut: 同步输出源

    • PWM_TB_SYNC_OUT_EVT_EPWMxSYNC

    • PWM_TB_SYNC_OUT_EVT_CTR_ZERO

    • PWM_TB_SYNC_OUT_EVT_DISABLE

10.2 PWM周期和占空比

PWMTimeBasePeriodSet()
 

 
void PWMTimeBasePeriodSet(
    unsigned int baseAddr,
    unsigned int period
);

功能: 设置PWM周期 参数:

  • period: 周期值 (0-65535)

周期计算:

 

 
// 向上/向下计数模式:
PWM频率 = TBCLK / period
// 增减计数模式:
PWM频率 = TBCLK / (2 × period)
PWMTBCounterValueSet()
 

 
void PWMTBCounterValueSet(
    unsigned int baseAddr,
    unsigned int counter
);

功能: 设置时基计数器初始值

PWMComparatorASet()
 

 
void PWMComparatorASet(
    unsigned int baseAddr,
    unsigned int compValue
);

功能: 设置比较器A的值 (控制占空比)

PWMComparatorBSet()
 

 
void PWMComparatorBSet(
    unsigned int baseAddr,
    unsigned int compValue
);

功能: 设置比较器B的值

10.3 PWM动作配置

PWMOutputActionConfig()
void PWMOutputActionConfig(
    unsigned int baseAddr,
    unsigned int channel,
    unsigned int event,
    unsigned int action
);

功能: 配置PWM输出动作 参数:

  • channel:

    • PWM_CHANNEL_A: 通道A

    • PWM_CHANNEL_B: 通道B

  • event: 事件类型

    • PWM_EVT_ZERO: 计数器=0

    • PWM_EVT_PRD: 计数器=周期

    • PWM_EVT_CAU: 计数器上升=CMPA

    • PWM_EVT_CAD: 计数器下降=CMPA

    • PWM_EVT_CBU: 计数器上升=CMPB

    • PWM_EVT_CBD: 计数器下降=CMPB

  • action: 动作

    • PWM_ACTION_DONOTHING: 无动作

    • PWM_ACTION_CLR: 清零(输出低)

    • PWM_ACTION_SET: 置位(输出高)

    • PWM_ACTION_TOGGLE: 翻转

典型配置示例:

// 向上计数模式,50%占空比PWM
PWMOutputActionConfig(baseAddr, PWM_CHANNEL_A,
                      PWM_EVT_ZERO, PWM_ACTION_SET);    // CTR=0时输出高
PWMOutputActionConfig(baseAddr, PWM_CHANNEL_A,
                      PWM_EVT_CAU, PWM_ACTION_CLR);     // CTR=CMPA时输出低

10.4 死区控制

PWMDeadBandConfig()
void PWMDeadBandConfig(
    unsigned int baseAddr,
    unsigned int inputMode,
    unsigned int outputMode,
    unsigned int polarity
);

功能: 配置死区发生器 参数:

  • inputMode: 输入模式

    • PWM_DB_IN_MODE_A_RED_A_FED: 通道A上升/下降

    • PWM_DB_IN_MODE_A_RED_B_FED: A上升,B下降

  • outputMode: 输出模式

    • PWM_DB_OUT_MODE_BYPASS: 旁路

    • PWM_DB_OUT_MODE_A_RED_A_FED: A带死区

    • PWM_DB_OUT_MODE_A_RED_B_FED: A上升B下降死区

  • polarity: 极性控制

    • PWM_DB_POL_ACTV_HIGH: 高电平有效

    • PWM_DB_POL_ACTV_LOW: 低电平有效

PWMDeadBandDelaySet()
void PWMDeadBandDelaySet(
    unsigned int baseAddr,
    unsigned int redDelay,
    unsigned int fedDelay
);

功能: 设置死区时间 参数:

  • redDelay: 上升沿延时 (0-1023个TBCLK周期)

  • fedDelay: 下降沿延时 (0-1023个TBCLK周期)

10.5 PWM中断和触发

PWMETIntEnable()
void PWMETIntEnable(
    unsigned int baseAddr,
    unsigned int intSrc
);

功能: 使能事件触发中断 参数:

  • intSrc: 中断源

    • PWM_ET_INT_TBCTR_ZERO: 计数器=0

    • PWM_ET_INT_TBCTR_PRD: 计数器=周期

    • PWM_ET_INT_TBCTR_CMPA_UP: 上升=CMPA

    • PWM_ET_INT_TBCTR_CMPA_DOWN: 下降=CMPA

PWMETIntPrescaleSet()
void PWMETIntPrescaleSet(
    unsigned int baseAddr,
    unsigned int prescale
);

功能: 设置中断预分频 参数:

  • prescale: 预分频值 (1-15)

    • PWM_ET_INT_PRD_FIRST: 第1次事件触发

    • PWM_ET_INT_PRD_SECOND: 第2次事件触发

    • PWM_ET_INT_PRD_THIRD: 第3次事件触发

PWMETIntStatusClear()
void PWMETIntStatusClear(unsigned int baseAddr);

功能: 清除事件触发中断标志

10.6 PWM保护功能

PWMTZTripEventEnable()
void PWMTZTripEventEnable(
    unsigned int baseAddr,
    unsigned int tzSrc,
    unsigned int event
);

功能: 使能故障保护事件 参数:

  • tzSrc: 故障源

    • PWM_TZ_SRC_OSHT1 ~ PWM_TZ_SRC_OSHT6: 单次故障

    • PWM_TZ_SRC_CYCLE_BC1 ~ PWM_TZ_SRC_CYCLE_BC6: 循环故障

  • event: 事件类型

    • PWM_TZ_EVENT_ONE_SHOT: 单次事件

    • PWM_TZ_EVENT_CYCLE_BY_CYCLE: 逐周期事件

PWMTZEventActionSet()
 

 
void PWMTZEventActionSet(
    unsigned int baseAddr,
    unsigned int channel,
    unsigned int event,
    unsigned int action
);

功能: 设置故障发生时PWM动作 参数:

  • action:

    • PWM_TZ_ACTION_HIGH_Z: 高阻态

    • PWM_TZ_ACTION_FORCE_HIGH: 强制高电平

    • PWM_TZ_ACTION_FORCE_LOW: 强制低电平

    • PWM_TZ_ACTION_DONOTHING: 无动作

10.7 完整应用示例

 

 
/****************************************************************************/
/*                        eHRPWM模块完整示例                                  */
/*                产生10kHz PWM,占空比可调,带死区控制                          */
/****************************************************************************/
#include "TMS320C6748.h"
#include "ehrpwm.h"
#include "psc.h"
#include "soc_C6748.h"
#define PWM_BASE        SOC_EPWM_0_REGS
#define PWM_FREQ        10000       /* PWM频率10kHz */
#define SYSCLK          150000000   /* 系统时钟150MHz */
/* 计算得到的周期值 */
#define PWM_PERIOD      (SYSCLK / PWM_FREQ)  /* 15000 */
volatile unsigned int dutyCycle = 50;  /* 占空比百分比 */
void PWMInit(void)
{
    /* 使能EPWM0模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_EPWM, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 使能时基时钟 */
    PWMTBClkSyncEnable(SOC_SYSCFG_0_REGS);
    /* 配置时钟分频: TBCLK = SYSCLK / 1 = 150MHz */
    EHRPWMClockConfigure(PWM_BASE, PWM_TB_CLK_DIV_1, PWM_HS_CLK_DIV_1);
    /* 配置时基: 向上计数模式 */
    EHRPWMTimebaseControl(PWM_BASE,
                          EHRPWM_SHADOW_WRITE_DISABLE,
                          EHRPWM_COUNTER_UP,
                          EHRPWM_FREEZE_TB_CLK_DISABLE);
    /* 设置周期值 */
    EHRPWMTimebasePeriodSet(PWM_BASE, PWM_PERIOD);
    /* 设置初始计数值 */
    EHRPWMTimebaseCounterSet(PWM_BASE, 0);
    /* 配置比较器A: 50%占空比 */
    EHRPWMCompASet(PWM_BASE, PWM_PERIOD * dutyCycle / 100);
    /* 配置动作:
     * CTR=0时输出高
     * CTR=CMPA时输出低 */
    EHRPWMConfigureAQActionOnA(PWM_BASE,
                                EHRPWM_AQCTLA_ZRO_SET,      /* CTR=0时置位 */
                                EHRPWM_AQCTLA_PRD_DONOTHING,
                                EHRPWM_AQCTLA_CAU_CLEAR,    /* CTR=CMPA上升时清零 */
                                EHRPWM_AQCTLA_CAD_DONOTHING,
                                EHRPWM_AQCTLA_CBU_DONOTHING,
                                EHRPWM_AQCTLA_CBD_DONOTHING);
    /* 配置死区 (可选,用于H桥驱动) */
    EHRPWMConfigureDeadband(PWM_BASE,
                            EHRPWM_DB_INPUT_EPWMA,
                            EHRPWM_DB_POLSEL_ALH,     /* 高电平有效 */
                            EHRPWM_DBCTL_OUT_MODE_BOTH);
    EHRPWMDeadbandDelaySet(PWM_BASE, 100, 100);  /* 100个TBCLK周期 */
    /* 禁用斩波器 */
    EHRPWMConfigureChopperClock(PWM_BASE, 0, 0, 0);
    /* 配置故障保护 (可选) */
    EHRPWMTZTripEventEnable(PWM_BASE, EHRPWM_TZ_SIGNAL_OSHT1, EHRPWM_TZ_TRIP_ONE_SHOT);
    EHRPWMTZActionOnEventOutput(PWM_BASE, EHRPWM_TZ_ACTION_FORCE_LOW, EHRPWM_TZ_ACTION_FORCE_LOW);
}
/* 设置占空比 (0-100%) */
void PWMSetDutyCycle(unsigned int duty)
{
    if(duty > 100) duty = 100;
    dutyCycle = duty;
    EHRPWMCompASet(PWM_BASE, PWM_PERIOD * duty / 100);
}
/* PWM中断配置示例 (每个周期产生一次中断) */
void PWMInterruptInit(void)
{
    /* 配置事件触发: CTR=0时产生中断 */
    EHRPWMETIntSourceSelect(PWM_BASE, EHRPWM_ETSEL_INTSEL_TBCTR_ZERO);
    /* 每个事件都产生中断 */
    EHRPWMETIntPeriodSelect(PWM_BASE, EHRPWM_ETPS_INTPRD_FIRSTEVT);
    /* 使能中断 */
    EHRPWMETIntEnable(PWM_BASE);
}
int main(void)
{
    PWMInit();
    /* 初始占空比50% */
    PWMSetDutyCycle(50);
    while(1)
    {
        /* 可在此动态调整占空比 */
        /* 例如: PWMSetDutyCycle(75); */
        /* 简单延时后改变占空比 */
        volatile int i;
        for(i = 0; i < 10000000; i++);
        /* 渐变占空比示例 */
        static unsigned int duty = 0;
        static int direction = 1;
        duty += direction;
        if(duty >= 100) direction = -1;
        if(duty <= 0) direction = 1;
        PWMSetDutyCycle(duty);
    }
}

11. ECAP_APWM模式

11.1 ECAP模式选择

ECAPOperatingModeSelect()
void ECAPOperatingModeSelect(
    unsigned int baseAddr,
    unsigned int mode
);

功能: 选择ECAP工作模式 参数:

  • mode:

    • ECAP_CAPTURE_MODE: 捕获模式

    • ECAP_APWM_MODE: 辅助PWM模式

11.2 APWM配置

ECAPAPWMCaptureConfig()
void ECAPAPWMCaptureConfig(
    unsigned int baseAddr,
    unsigned int compareVal,
    unsigned int periodVal
);

功能: 配置APWM周期和比较值 参数:

  • compareVal: 比较值 (控制占空比)

  • periodVal: 周期值

寄存器映射:

  • CAP1寄存器 → 周期寄存器

  • CAP2寄存器 → 比较寄存器

计算公式:

ECAP时钟 = PLL1_SYSCLK1 / 2 = 228MHz

PWM频率 = ECAP时钟 / periodVal
占空比 = compareVal / periodVal

示例: periodVal=22800, compareVal=11400
  频率 = 228MHz / 22800 = 10KHz
  占空比 = 11400 / 22800 = 50%
ECAPAPWMPolarityConfig()
void ECAPAPWMPolarityConfig(
    unsigned int baseAddr,
    unsigned int polarity
);

功能: 配置APWM极性 参数:

  • polarity:

    • ECAP_APWM_ACTIVE_HIGH: 高电平有效

    • ECAP_APWM_ACTIVE_LOW: 低电平有效

说明:

  • 高电平有效: 比较值定义高电平时间

  • 低电平有效: 比较值定义低电平时间

11.3 ECAP计数器控制

ECAPCounterControl()
 

 
void ECAPCounterControl(
    unsigned int baseAddr,
    unsigned int mode
);

功能: 控制计数器运行 参数:

  • mode:

    • ECAP_COUNTER_STOP: 停止计数

    • ECAP_COUNTER_FREE_RUNNING: 自由运行

11.4 ECAP中断

ECAPIntEnable()
 

 
void ECAPIntEnable(
    unsigned int baseAddr,
    unsigned int flag
);

功能: 使能ECAP中断 参数:

  • flag: 中断类型

    • ECAP_CEVT1_INT: 捕获事件1中断

    • ECAP_CEVT2_INT: 捕获事件2中断

    • ECAP_CEVT3_INT: 捕获事件3中断

    • ECAP_CEVT4_INT: 捕获事件4中断

    • ECAP_CTROVF_INT: 计数器溢出中断

    • ECAP_CMPEQ_INT: 比较相等中断 (CTR=CMP)

    • ECAP_PRDEQ_INT: 周期相等中断 (CTR=PRD)

ECAPIntDisable()
void ECAPIntDisable(
    unsigned int baseAddr,
    unsigned int flag
);

功能: 禁用ECAP中断

ECAPIntStatusClear()
void ECAPIntStatusClear(
    unsigned int baseAddr,
    unsigned int flag
);

功能: 清除ECAP中断标志

ECAPGlobalIntEnable()
void ECAPGlobalIntEnable(unsigned int baseAddr);

功能: 使能ECAP全局中断 (清除INT标志)

11.5 捕获模式配置 (参考)

ECAPCaptureEvtPolarityConfig()
void ECAPCaptureEvtPolarityConfig(
    unsigned int baseAddr,
    unsigned int evtNum,
    unsigned int polarity
);

功能: 配置捕获事件触发极性 参数:

  • evtNum: 事件号 (ECAP_CEVT1 ~ ECAP_CEVT4)

  • polarity:

    • ECAP_CAPTURE_EVT_RISING_EDGE: 上升沿

    • ECAP_CAPTURE_EVT_FALLING_EDGE: 下降沿

ECAPCaptureEvtCntrRstConfig()
void ECAPCaptureEvtCntrRstConfig(
    unsigned int baseAddr,
    unsigned int evtNum,
    unsigned int reset
);

功能: 配置捕获事件是否复位计数器

11.6 完整应用示例

/****************************************************************************/
/*                        ECAP APWM模式完整示例                               */
/*                    产生10kHz PWM,占空比可调                                */
/****************************************************************************/
#include "TMS320C6748.h"
#include "ecap.h"
#include "interrupt.h"
#include "psc.h"
#include "soc_C6748.h"

#define ECAP_BASE       SOC_ECAP_2_REGS
#define ECAP_CLK        228000000   /* ECAP时钟228MHz */
#define PWM_FREQ        10000       /* PWM频率10kHz */

/* 计算周期值: 228MHz / 10kHz = 22800 */
#define PWM_PERIOD      (ECAP_CLK / PWM_FREQ)

volatile unsigned int pwmIntCount = 0;

/* ECAP中断服务函数 */
void ECAPIsr(void)
{
    /* 检查周期中断 */
    if(ECAPIntStatus(ECAP_BASE, ECAP_PRDEQ_INT))
    {
        ECAPIntStatusClear(ECAP_BASE, ECAP_PRDEQ_INT);
        pwmIntCount++;
    }

    /* 清除全局中断标志 */
    ECAPGlobalIntEnable(ECAP_BASE);
    IntEventClear(SYS_INT_ECAP_SELECT);
}

void ECAPInit(void)
{
    /* 使能ECAP2模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_ECAP2, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);

    /* 停止计数器 */
    ECAPCounterControl(ECAP_BASE, ECAP_COUNTER_STOP);

    /* 选择APWM模式 */
    ECAPOperatingModeSelect(ECAP_BASE, ECAP_APWM_MODE);

    /* 配置APWM周期和占空比 (50%) */
    ECAPAPWMCaptureConfig(ECAP_BASE, PWM_PERIOD / 2, PWM_PERIOD);

    /* 配置极性: 高电平有效 */
    ECAPAPWMPolarityConfig(ECAP_BASE, ECAP_APWM_ACTIVE_HIGH);

    /* 使能周期中断 */
    ECAPIntEnable(ECAP_BASE, ECAP_PRDEQ_INT);

    /* 启动计数器 */
    ECAPCounterControl(ECAP_BASE, ECAP_COUNTER_FREE_RUNNING);
}

/* 设置占空比 (0-100%) */
void ECAPSetDutyCycle(unsigned int duty)
{
    unsigned int compareVal;

    if(duty > 100) duty = 100;
    compareVal = (PWM_PERIOD * duty) / 100;

    /* 停止计数器 */
    ECAPCounterControl(ECAP_BASE, ECAP_COUNTER_STOP);

    /* 更新比较值 */
    ECAPAPWMCaptureConfig(ECAP_BASE, compareVal, PWM_PERIOD);

    /* 重启计数器 */
    ECAPCounterControl(ECAP_BASE, ECAP_COUNTER_FREE_RUNNING);
}

void InterruptInit(void)
{
    IntDSPINTCInit();

    /* 注册ECAP中断 */
    IntRegister(C674X_MASK_INT4, ECAPIsr);
    IntEventMap(C674X_MASK_INT4, SYS_INT_ECAP_SELECT);
    IntEnable(C674X_MASK_INT4);
    IntGlobalEnable();
}

int main(void)
{
    ECAPInit();
    InterruptInit();

    /* 初始占空比50% */
    ECAPSetDutyCycle(50);

    while(1)
    {
        /* 渐变占空比示例 */
        volatile int i;
        static unsigned int duty = 0;
        static int direction = 1;

        for(i = 0; i < 5000000; i++);

        duty += direction;
        if(duty >= 100) direction = -1;
        if(duty <= 0) direction = 1;

        ECAPSetDutyCycle(duty);
    }
}

12. 看门狗定时器

12.1 看门狗配置

看门狗使用Timer1的64位模式:

TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_64BIT_WATCHDOG);

12.2 看门狗周期设置

void TimerWatchDogInit(void) {
    // 配置为看门狗模式
    TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_64BIT_WATCHDOG);

    // 设置周期 (24MHz时钟,5秒超时)
    TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER12, 120000000);  // 低32位
    TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER34, 0);          // 高32位

    // 激活看门狗
    TimerWatchdogActivate(SOC_TMR_1_REGS);
}

周期计算:

看门狗周期 = 周期值 / 时钟频率
         = 120000000 / 24MHz
         = 5秒

12.3 看门狗激活

TimerWatchdogActivate()
void TimerWatchdogActivate(unsigned int baseAddr);

功能: 激活看门狗定时器

内部实现:

void TimerWatchdogActivate(unsigned int baseAddr) {
    // 写密钥A5C6,进入pre-active状态
    HWREG(baseAddr + TMR_WDTCR) =
        (TMR_WDTCR_WDEN | TMR_WDTCR_WDFLAG) |
        (0xA5C6 << TMR_WDTCR_WDKEY_SHIFT);

    // 写密钥DA7E,进入active状态
    HWREG(baseAddr + TMR_WDTCR) =
        (HWREG(baseAddr + TMR_WDTCR) & (~TMR_WDTCR_WDKEY)) |
        (0xDA7E << TMR_WDTCR_WDKEY_SHIFT);
}

12.4 喂狗操作

TimerWatchdogReactivate()
void TimerWatchdogReactivate(unsigned int baseAddr);

功能: "喂狗"操作,复位看门狗计数器

内部实现:

 

 
void TimerWatchdogReactivate(unsigned int baseAddr) {
    // 写密钥A5C6,进入service状态
    HWREG(baseAddr + TMR_WDTCR) =
        (HWREG(baseAddr + TMR_WDTCR) & (~TMR_WDTCR_WDKEY)) |
        (0xA5C6 << TMR_WDTCR_WDKEY_SHIFT);
    // 写密钥DA7E,回到active状态,计数器清零
    HWREG(baseAddr + TMR_WDTCR) =
        (HWREG(baseAddr + TMR_WDTCR) & (~TMR_WDTCR_WDKEY)) |
        (0xDA7E << TMR_WDTCR_WDKEY_SHIFT);
}

12.5 看门狗密钥

密钥值状态转换
0xA5C6Active → Service (喂狗第1步) <br> 或 Initial → Pre-Active (激活第1步)
0xDA7EPre-Active → Active (激活第2步) <br> 或 Service → Active (喂狗第2步)

状态机:

 

 
Initial → [A5C6] → Pre-Active → [DA7E] → Active
                                            ↓
                                        [A5C6]
                                            ↓
                                        Service
                                            ↓
                                        [DA7E]
                                            ↓
                                        Active (计数器清零)

12.6 完整应用示例

 

 
/****************************************************************************/
/*                          看门狗定时器完整示例                               */
/*                  5秒超时,主循环中定期喂狗防止复位                            */
/****************************************************************************/
#include "TMS320C6748.h"
#include "timer.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"
#define WDT_BASE        SOC_TMR_1_REGS
#define WDT_CLK         24000000    /* 看门狗时钟24MHz */
#define WDT_TIMEOUT_SEC 5           /* 超时时间5秒 */
#define LED_PIN         109         /* GPIO6[12] */
volatile unsigned int feedCount = 0;
/* 看门狗初始化 */
void WatchdogInit(void)
{
    /* 使能Timer1模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TMR1, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置为64位看门狗模式 */
    TimerConfigure(WDT_BASE, TMR_CFG_64BIT_WATCHDOG);
    /* 设置超时周期 (5秒) */
    TimerPeriodSet(WDT_BASE, TMR_TIMER12, WDT_CLK * WDT_TIMEOUT_SEC);
    TimerPeriodSet(WDT_BASE, TMR_TIMER34, 0);
    /* 激活看门狗 (使用两步密钥序列) */
    TimerWatchdogActivate(WDT_BASE);
}
/* 喂狗操作 */
void WatchdogFeed(void)
{
    TimerWatchdogReactivate(WDT_BASE);
    feedCount++;
}
/* 延时函数 (约1秒) */
void Delay1Sec(void)
{
    volatile unsigned int i;
    for(i = 0; i < 10000000; i++);
}
int main(void)
{
    /* 配置LED */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    GPIODirModeSet(SOC_GPIO_0_REGS, LED_PIN, GPIO_DIR_OUTPUT);
    /* 检查是否是看门狗复位 (通过检测特定标志) */
    /* 上电后LED闪烁表示正常启动 */
    GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_HIGH);
    Delay1Sec();
    GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_LOW);
    /* 初始化看门狗 (5秒超时) */
    WatchdogInit();
    while(1)
    {
        /* 正常操作: 每2秒喂狗一次 (在5秒超时内) */
        Delay1Sec();
        Delay1Sec();
        /* 喂狗 */
        WatchdogFeed();
        /* LED翻转表示正常运行 */
        if(feedCount % 2)
            GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_HIGH);
        else
            GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_LOW);
        /* 如果不喂狗,5秒后系统会自动复位 */
        /* 可通过注释掉WatchdogFeed()测试看门狗复位功能 */
    }
}

13. NMI不可屏蔽中断

13.1 NMI注册

IntRegister() - NMI版本
IntRegister(C674X_MASK_NMI, NMIIsr);

功能: 注册NMI中断处理函数 参数:

  • C674X_MASK_NMI: NMI中断号(固定为1)

  • NMIIsr: 中断服务函数

注意: NMI不需要调用IntEnable(),因为它不可屏蔽

13.2 NMI中断服务函数

必须使用特殊的Pragma指令:

#pragma NMI_INTERRUPT(NMIIsr)
void NMIIsr(void) {
    // 紧急处理代码
    SaveCriticalData();
    EnterSafeMode();
}

Pragma指令: #pragma NMI_INTERRUPT(function_name)

13.3 NMI特性

特性NMI普通中断
可屏蔽❌ 不可屏蔽✅ 可屏蔽
中断号固定为14-15
需要使能❌ 自动响应✅ 需要IntEnable()
Pragma#pragma NMI_INTERRUPT#pragma INTERRUPT
触发方式硬件引脚低电平系统事件映射
优先级最高按中断号

13.4 NMI触发

  • 引脚: NMI / NMIZ

  • 触发电平: 低电平有效

  • 中断事件: NMEVT

  • 应用场景:

    • 掉电检测

    • 看门狗超时

    • 严重硬件错误

    • 紧急停机

13.5 完整应用示例

/****************************************************************************/
/*                         NMI不可屏蔽中断完整示例                              */
/*                      用于紧急处理如掉电检测等情况                             */
/****************************************************************************/
#include "TMS320C6748.h"
#include "interrupt.h"
#include "gpio.h"
#include "psc.h"
#include "soc_C6748.h"

#define LED_PIN         109         /* GPIO6[12] */
#define BACKUP_ADDR     0x80000000  /* 备份数据存储地址 */

/* 关键数据结构 */
typedef struct {
    unsigned int systemState;
    unsigned int dataCount;
    unsigned int checksum;
} CriticalData_t;

volatile CriticalData_t criticalData = {0, 0, 0};
volatile unsigned int nmiCount = 0;

/* NMI中断服务函数 - 必须使用#pragma NMI_INTERRUPT */
#pragma NMI_INTERRUPT(NMIIsr)
void NMIIsr(void)
{
    nmiCount++;

    /* 紧急处理: 保存关键数据 */
    CriticalData_t *backup = (CriticalData_t *)BACKUP_ADDR;
    backup->systemState = criticalData.systemState;
    backup->dataCount = criticalData.dataCount;
    backup->checksum = criticalData.systemState ^ criticalData.dataCount;

    /* 设置安全状态标志 */
    GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_HIGH);

    /* 进入安全模式 */
    /* 可以在此关闭危险设备、保存状态等 */

    /* NMI不需要手动清除中断标志 */
}

void NMIInit(void)
{
    /* 初始化DSP中断控制器 */
    IntDSPINTCInit();

    /* 注册NMI中断处理函数 */
    /* NMI使用C674X_MASK_NMI,中断号固定为1 */
    IntRegister(C674X_MASK_NMI, NMIIsr);

    /* 注意: NMI不需要调用IntEnable(),因为它不可屏蔽 */
    /* 也不需要调用IntGlobalEnable()来使能NMI */

    /* 使能全局中断 (仅用于其他可屏蔽中断) */
    IntGlobalEnable();
}

int main(void)
{
    /* 配置GPIO */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    GPIODirModeSet(SOC_GPIO_0_REGS, LED_PIN, GPIO_DIR_OUTPUT);
    GPIOPinWrite(SOC_GPIO_0_REGS, LED_PIN, GPIO_PIN_LOW);

    /* 初始化NMI中断 */
    NMIInit();

    /* 初始化关键数据 */
    criticalData.systemState = 1;
    criticalData.dataCount = 0;

    while(1)
    {
        /* 正常操作 */
        criticalData.dataCount++;

        /* 简单延时 */
        volatile int i;
        for(i = 0; i < 1000000; i++);

        /* 当NMI引脚被拉低时,会自动触发NMI中断 */
        /* NMI通常连接到掉电检测电路 */
    }
}

14. RTC实时时钟

14.1 RTC初始化

RTCWriteProtectDisable()
void RTCWriteProtectDisable(unsigned int baseAddr);

功能: 解除RTC寄存器写保护

内部实现:

void RTCWriteProtectDisable(unsigned int baseAddr) {
    HWREG(baseAddr + RTC_KICK0) = 0x83E70B13;  // 密钥Key0
    HWREG(baseAddr + RTC_KICK1) = 0x95A4F1E0;  // 密钥Key1
}
RTCEnable()
void RTCEnable(unsigned int baseAddr);

功能: 使能RTC模块

内部实现:

void RTCEnable(unsigned int baseAddr) {
    // 软件复位RTC
    HWREG(baseAddr + RTC_OSC) |= RTC_OSC_SWRESET;

    // 清除RTCDISABLE位
    HWREG(baseAddr + RTC_CTRL) &= ~RTC_CTRL_RTCDISABLE;

    // 使能独立供电模式 (纽扣电池)
    HWREG(baseAddr + RTC_CTRL) |= RTC_CTRL_SPLITPOWER;
}

注意: 软件复位后必须延时至少3个RTC时钟周期 (约91.5μs @ 32KHz)

14.2 RTC时间设置

RTCTimeSet()
void RTCTimeSet(
    unsigned int baseAddr,
    unsigned int time
);

功能: 设置RTC时间 参数:

  • time: 时间值 (BCD码格式)

    • Bit[23:16]: 时 (0x00-0x23)

    • Bit[15:8]: 分 (0x00-0x59)

    • Bit[7:0]: 秒 (0x00-0x59)

内部实现:

 

 
void RTCTimeSet(unsigned int baseAddr, unsigned int time) {
    // 停止RTC计数器
    HWREG(baseAddr + RTC_CTRL) &= ~RTC_CTRL_RUN;
    // 使能独立供电
    HWREG(baseAddr + RTC_CTRL) |= RTC_CTRL_SPLITPOWER;
    // 写入时分秒 (BCD码)
    HWREG(baseAddr + RTC_SECOND) = (time >> 0) & 0xFF;
    HWREG(baseAddr + RTC_MINUTE) = (time >> 8) & 0xFF;
    HWREG(baseAddr + RTC_HOUR) = (time >> 16) & 0xFF;
}
RTCTimeGet()
 

 
unsigned int RTCTimeGet(unsigned int baseAddr);

功能: 读取RTC当前时间 返回: BCD码格式的时间值

14.3 RTC日期设置

RTCCalendarSet()
 

 
void RTCCalendarSet(
    unsigned int baseAddr,
    unsigned int calendar
);

功能: 设置RTC日期 参数:

  • calendar: 日期值 (BCD码格式)

    • Bit[23:16]: 年 (0x00-0x99)

    • Bit[15:8]: 月 (0x01-0x12)

    • Bit[7:0]: 日 (0x01-0x31)

内部实现:

void RTCCalendarSet(unsigned int baseAddr, unsigned int calendar) {
    // 等待RTC空闲
    while(HWREG(baseAddr + RTC_STATUS) & RTC_STATUS_BUSY);

    // 写入年月日 (BCD码)
    HWREG(baseAddr + RTC_YEAR) = (calendar >> 16) & 0xFF;
    HWREG(baseAddr + RTC_MONTH) = (calendar >> 8) & 0xFF;
    HWREG(baseAddr + RTC_DAY) = (calendar >> 0) & 0xFF;

    // 写入星期 (0=周日, 6=周六)
    HWREG(baseAddr + RTC_DOTW) = (calendar >> 24) & 0x07;
}
RTCCalendarGet()
unsigned int RTCCalendarGet(unsigned int baseAddr);

功能: 读取RTC当前日期

14.4 RTC计数器控制

RTCRun()
void RTCRun(unsigned int baseAddr);

功能: 启动RTC计数器

内部实现:

void RTCRun(unsigned int baseAddr) {
    HWREG(baseAddr + RTC_CTRL) |=
        (RTC_CTRL_RUN | RTC_CTRL_SPLITPOWER);
}

14.5 RTC中断

RTCIntTimerEnable()
void RTCIntTimerEnable(
    unsigned int baseAddr,
    unsigned int timerPeriod
);

功能: 使能RTC周期中断 参数:

  • timerPeriod: 中断周期

    • RTC_INT_EVERY_SECOND: 每秒

    • RTC_INT_EVERY_MINUTE: 每分钟

    • RTC_INT_EVERY_HOUR: 每小时

    • RTC_INT_EVERY_DAY: 每天

内部实现:

void RTCIntTimerEnable(unsigned int baseAddr, unsigned int timerPeriod) {
    // 等待RTC空闲
    while(HWREG(baseAddr + RTC_STATUS) & RTC_STATUS_BUSY);

    // 使能定时中断
    HWREG(baseAddr + RTC_INTERRUPT) |= RTC_INTERRUPTS_TIMER;

    // 设置中断周期
    HWREG(baseAddr + RTC_INTERRUPT) |=
        (timerPeriod & RTC_INTERRUPTS_EVERY);
}
RTCIntAlarmEnable()
void RTCIntAlarmEnable(unsigned int baseAddr);

功能: 使能RTC闹钟中断

RTCAlarmHourSet()
void RTCAlarmHourSet(
    unsigned int baseAddr,
    unsigned int hour
);

功能: 设置闹钟时 (BCD码)

RTCAlarmMinuteSet()
void RTCAlarmMinuteSet(
    unsigned int baseAddr,
    unsigned int minute
);

功能: 设置闹钟分 (BCD码)

RTCAlarmSecondSet()
void RTCAlarmSecondSet(
    unsigned int baseAddr,
    unsigned int second
);

功能: 设置闹钟秒 (BCD码)

14.6 BCD码转换

DecimalToBCD()
unsigned char DecimalToBCD(unsigned char decimal);

功能: 十进制转BCD码

实现:

unsigned char DecimalToBCD(unsigned char decimal) {
    return ((decimal / 10) << 4) | (decimal % 10);
}
BCDToDecimal()
unsigned char BCDToDecimal(unsigned char bcd);

功能: BCD码转十进制

实现:

unsigned char BCDToDecimal(unsigned char bcd) {
    return ((bcd >> 4) * 10) + (bcd & 0x0F);
}

14.7 完整应用示例

 

 
/****************************************************************************/
/*                          RTC实时时钟完整示例                                */
/*               设置时间日期,每秒产生中断,支持闹钟功能                          */
/****************************************************************************/
#include "TMS320C6748.h"
#include "rtc.h"
#include "interrupt.h"
#include "psc.h"
#include "soc_C6748.h"
#define RTC_BASE    SOC_RTC_0_REGS
/* BCD码转换 */
#define DEC_TO_BCD(dec)     (((dec)/10)<<4)|((dec)%10)
#define BCD_TO_DEC(bcd)     (((bcd)>>4)*10)+((bcd)&0x0F)
volatile unsigned int rtcIntCount = 0;
volatile unsigned int alarmTriggered = 0;
/* RTC中断服务函数 */
void RTCIsr(void)
{
    unsigned int intStatus;
    /* 读取中断状态 */
    intStatus = RTCIntStatusGet(RTC_BASE);
    /* 处理周期中断 (每秒) */
    if(intStatus & RTC_INT_TIMER)
    {
        rtcIntCount++;
        RTCIntStatusClear(RTC_BASE, RTC_INT_TIMER);
    }
    /* 处理闹钟中断 */
    if(intStatus & RTC_INT_ALARM)
    {
        alarmTriggered = 1;
        RTCIntStatusClear(RTC_BASE, RTC_INT_ALARM);
    }
    IntEventClear(SYS_INT_RTC_IRQS);
}
/* 延时函数 (RTC复位后需要等待) */
void DelayRTC(void)
{
    volatile unsigned int i;
    for(i = 0; i < 10000; i++);  /* 约100us */
}
void RTCInit(void)
{
    /* 使能RTC模块 */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_RTC, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 解除写保护 (使用密钥序列) */
    RTCWriteProtectDisable(RTC_BASE);
    /* 使能RTC */
    RTCEnable(RTC_BASE);
    /* 等待RTC稳定 */
    DelayRTC();
}
/* 设置时间 (时:分:秒) */
void RTCSetTime(unsigned int hour, unsigned int min, unsigned int sec)
{
    unsigned int time;
    /* 转换为BCD码 */
    time = (DEC_TO_BCD(hour) << 16) |
           (DEC_TO_BCD(min) << 8) |
           DEC_TO_BCD(sec);
    /* 停止计数器 */
    RTCRun(RTC_BASE);
    /* 等待RTC空闲 */
    while(RTCBusyStatusGet(RTC_BASE));
    /* 设置时间 */
    RTCTimeSet(RTC_BASE, time);
}
/* 设置日期 (年:月:日) */
void RTCSetDate(unsigned int year, unsigned int month, unsigned int day)
{
    unsigned int calendar;
    /* 转换为BCD码 */
    calendar = (DEC_TO_BCD(year) << 16) |
               (DEC_TO_BCD(month) << 8) |
               DEC_TO_BCD(day);
    /* 等待RTC空闲 */
    while(RTCBusyStatusGet(RTC_BASE));
    /* 设置日期 */
    RTCCalendarSet(RTC_BASE, calendar);
}
/* 设置闹钟 (时:分:秒) */
void RTCSetAlarm(unsigned int hour, unsigned int min, unsigned int sec)
{
    while(RTCBusyStatusGet(RTC_BASE));
    RTCAlarmHourSet(RTC_BASE, DEC_TO_BCD(hour));
    RTCAlarmMinuteSet(RTC_BASE, DEC_TO_BCD(min));
    RTCAlarmSecondSet(RTC_BASE, DEC_TO_BCD(sec));
    /* 使能闹钟中断 */
    RTCIntAlarmEnable(RTC_BASE);
}
/* 读取当前时间 */
void RTCGetTime(unsigned int *hour, unsigned int *min, unsigned int *sec)
{
    unsigned int time;
    while(RTCBusyStatusGet(RTC_BASE));
    time = RTCTimeGet(RTC_BASE);
    *hour = BCD_TO_DEC((time >> 16) & 0xFF);
    *min = BCD_TO_DEC((time >> 8) & 0xFF);
    *sec = BCD_TO_DEC(time & 0xFF);
}
void InterruptInit(void)
{
    IntDSPINTCInit();
    IntRegister(C674X_MASK_INT4, RTCIsr);
    IntEventMap(C674X_MASK_INT4, SYS_INT_RTC_IRQS);
    IntEnable(C674X_MASK_INT4);
    IntGlobalEnable();
}
int main(void)
{
    unsigned int hour, min, sec;
    RTCInit();
    InterruptInit();
    /* 设置初始时间: 12:00:00 */
    RTCSetTime(12, 0, 0);
    /* 设置日期: 2026-01-03 */
    RTCSetDate(26, 1, 3);
    /* 设置闹钟: 12:00:30 */
    RTCSetAlarm(12, 0, 30);
    /* 使能每秒中断 */
    RTCIntTimerEnable(RTC_BASE, RTC_INT_EVERY_SECOND);
    /* 启动RTC */
    RTCRun(RTC_BASE);
    while(1)
    {
        /* 每秒读取并处理时间 */
        if(rtcIntCount > 0)
        {
            rtcIntCount = 0;
            RTCGetTime(&hour, &min, &sec);
            /* 在此可通过UART输出时间 */
        }
        /* 检查闹钟 */
        if(alarmTriggered)
        {
            alarmTriggered = 0;
            /* 闹钟触发处理 */
        }
    }
}

15. EMIF访问NAND Flash

15.1 EMIF地址计算

地址计算公式
// 基地址 (CS3片选)
#define NAND_BASE_ADDR    0x62000000

// 三种访问地址
#define NAND_DATA_ADDR    (NAND_BASE_ADDR + 0x00)  // CLE=0, ALE=0
#define NAND_ADDR_ADDR    (NAND_BASE_ADDR + 0x08)  // CLE=0, ALE=1
#define NAND_CMD_ADDR     (NAND_BASE_ADDR + 0x10)  // CLE=1, ALE=0

计算原理:

硬件连接: ALE → EMA_A1, CLE → EMA_A2
8位设备: EMA_BA[1:0]占用低2位,所以地址左移2位

锁存数据: A2=0, A1=0 → 偏移 = 0 << 2 = 0x00
锁存地址: A2=0, A1=1 → 偏移 = 2 << 2 = 0x08
锁存命令: A2=1, A1=0 → 偏移 = 4 << 2 = 0x10

15.2 NAND Flash访问宏

NAND_WRITE_CMD()
#define NAND_WRITE_CMD(cmd) \
    (*((volatile uint8_t *)NAND_CMD_ADDR) = (cmd))

功能: 写入NAND Flash命令

NAND_WRITE_ADDR()
#define NAND_WRITE_ADDR(addr) \
    (*((volatile uint8_t *)NAND_ADDR_ADDR) = (addr))

功能: 写入NAND Flash地址

NAND_WRITE_DATA()
#define NAND_WRITE_DATA(data) \
    (*((volatile uint8_t *)NAND_DATA_ADDR) = (data))

功能: 写入NAND Flash数据

NAND_READ_DATA()
#define NAND_READ_DATA() \
    (*((volatile uint8_t *)NAND_DATA_ADDR))

功能: 读取NAND Flash数据

15.3 NAND Flash操作函数

NANDReadPage()
void NANDReadPage(
    uint32_t pageAddr,
    uint8_t *buffer,
    uint16_t size
);

功能: 读取NAND Flash页面

实现:

void NANDReadPage(uint32_t pageAddr, uint8_t *buffer, uint16_t size) {
    // 发送读命令
    NAND_WRITE_CMD(0x00);

    // 发送5个地址周期
    NAND_WRITE_ADDR(0x00);                      // 列地址低字节
    NAND_WRITE_ADDR(0x00);                      // 列地址高字节
    NAND_WRITE_ADDR((pageAddr >> 0) & 0xFF);    // 行地址周期1
    NAND_WRITE_ADDR((pageAddr >> 8) & 0xFF);    // 行地址周期2
    NAND_WRITE_ADDR((pageAddr >> 16) & 0xFF);   // 行地址周期3

    // 发送读确认命令
    NAND_WRITE_CMD(0x30);

    // 等待就绪
    while(!NANDIsReady());

    // 读取数据
    for(uint16_t i = 0; i < size; i++) {
        buffer[i] = NAND_READ_DATA();
    }
}
NANDWritePage()
 

 
void NANDWritePage(
    uint32_t pageAddr,
    uint8_t *buffer,
    uint16_t size
);

功能: 写入NAND Flash页面

实现:

 

 
void NANDWritePage(uint32_t pageAddr, uint8_t *buffer, uint16_t size) {
    // 发送页编程命令
    NAND_WRITE_CMD(0x80);
    // 发送地址
    NAND_WRITE_ADDR(0x00);
    NAND_WRITE_ADDR(0x00);
    NAND_WRITE_ADDR((pageAddr >> 0) & 0xFF);
    NAND_WRITE_ADDR((pageAddr >> 8) & 0xFF);
    NAND_WRITE_ADDR((pageAddr >> 16) & 0xFF);
    // 写入数据
    for(uint16_t i = 0; i < size; i++) {
        NAND_WRITE_DATA(buffer[i]);
    }
    // 发送编程确认命令
    NAND_WRITE_CMD(0x10);
    // 等待完成
    while(!NANDIsReady());
}
NANDEraseBlock()
 

 
void NANDEraseBlock(uint32_t blockAddr);

功能: 擦除NAND Flash块

实现:

void NANDEraseBlock(uint32_t blockAddr) {
    // 发送擦除命令
    NAND_WRITE_CMD(0x60);

    // 发送块地址 (3个地址周期)
    NAND_WRITE_ADDR((blockAddr >> 0) & 0xFF);
    NAND_WRITE_ADDR((blockAddr >> 8) & 0xFF);
    NAND_WRITE_ADDR((blockAddr >> 16) & 0xFF);

    // 发送擦除确认命令
    NAND_WRITE_CMD(0xD0);

    // 等待完成
    while(!NANDIsReady());
}
NANDReadID()
void NANDReadID(uint8_t *id);

功能: 读取NAND Flash ID

实现:

void NANDReadID(uint8_t *id) {
    NAND_WRITE_CMD(0x90);     // Read ID命令
    NAND_WRITE_ADDR(0x00);    // 地址0x00

    // 读取ID字节
    for(int i = 0; i < 5; i++) {
        id[i] = NAND_READ_DATA();
    }
}

15.4 NAND Flash命令集

命令代码说明
Read0x00 → 0x30读页面 (两周期命令)
Program0x80 → 0x10编程页面
Erase0x60 → 0xD0擦除块
Read ID0x90读取芯片ID
Reset0xFF复位Flash
Read Status0x70读状态寄存器

15.5 EMIF异步配置

EMIFAsyncCSConfig()
void EMIFAsyncCSConfig(
    unsigned int baseAddr,
    unsigned int csNum,
    unsigned int config
);

功能: 配置EMIF异步片选

示例:

void EMIFAsyncCS3Init(void) {
    HWREG(SOC_EMIFA_0_REGS + EMIF_ASYNC_CS3_CR) =
        (0 << 31) |      // SS=0 (异步模式)
        (1 << 30) |      // EW=1 (8位数据总线)
        (5 << 26) |      // W_SETUP
        (10 << 20) |     // W_STROBE
        (2 << 17) |      // W_HOLD
        (5 << 13) |      // R_SETUP
        (10 << 7) |      // R_STROBE
        (2 << 4) |       // R_HOLD
        (1 << 0);        // TA (Turn Around)
}

15.6 完整应用示例

 

 
/****************************************************************************/
/*                       EMIF NAND Flash访问完整示例                          */
/*                    通过EMIF异步接口访问NAND Flash                           */
/****************************************************************************/
#include "TMS320C6748.h"
#include "emifa.h"
#include "psc.h"
#include "soc_C6748.h"
/* NAND Flash地址定义 (CS3片选) */
#define NAND_BASE_ADDR    0x62000000
#define NAND_DATA_ADDR    (NAND_BASE_ADDR + 0x00)  /* CLE=0, ALE=0: 数据 */
#define NAND_ADDR_ADDR    (NAND_BASE_ADDR + 0x08)  /* CLE=0, ALE=1: 地址 */
#define NAND_CMD_ADDR     (NAND_BASE_ADDR + 0x10)  /* CLE=1, ALE=0: 命令 */
/* NAND Flash命令 */
#define NAND_CMD_READ1        0x00
#define NAND_CMD_READ2        0x30
#define NAND_CMD_PROGRAM1     0x80
#define NAND_CMD_PROGRAM2     0x10
#define NAND_CMD_ERASE1       0x60
#define NAND_CMD_ERASE2       0xD0
#define NAND_CMD_READID       0x90
#define NAND_CMD_STATUS       0x70
#define NAND_CMD_RESET        0xFF
/* 访问宏 */
#define NAND_WRITE_CMD(cmd)   (*(volatile unsigned char *)NAND_CMD_ADDR = (cmd))
#define NAND_WRITE_ADDR(addr) (*(volatile unsigned char *)NAND_ADDR_ADDR = (addr))
#define NAND_WRITE_DATA(data) (*(volatile unsigned char *)NAND_DATA_ADDR = (data))
#define NAND_READ_DATA()      (*(volatile unsigned char *)NAND_DATA_ADDR)
/* 简单延时 */
void NANDDelay(void)
{
    volatile unsigned int i;
    for(i = 0; i < 100; i++);
}
/* 等待NAND就绪 */
void NANDWaitReady(void)
{
    unsigned char status;
    do {
        NAND_WRITE_CMD(NAND_CMD_STATUS);
        status = NAND_READ_DATA();
    } while(!(status & 0x40));  /* 检查RDY位 */
}
/* 读取NAND Flash ID */
void NANDReadID(unsigned char *id)
{
    unsigned int i;
    NAND_WRITE_CMD(NAND_CMD_READID);
    NAND_WRITE_ADDR(0x00);
    NANDDelay();
    for(i = 0; i < 5; i++)
    {
        id[i] = NAND_READ_DATA();
    }
}
/* 读取页面数据 */
void NANDReadPage(unsigned int pageAddr, unsigned char *buffer, unsigned int len)
{
    unsigned int i;
    /* 发送读命令 (第一周期) */
    NAND_WRITE_CMD(NAND_CMD_READ1);
    /* 发送地址 (5个周期) */
    NAND_WRITE_ADDR(0x00);                      /* 列地址低字节 */
    NAND_WRITE_ADDR(0x00);                      /* 列地址高字节 */
    NAND_WRITE_ADDR((pageAddr >> 0) & 0xFF);    /* 行地址周期1 */
    NAND_WRITE_ADDR((pageAddr >> 8) & 0xFF);    /* 行地址周期2 */
    NAND_WRITE_ADDR((pageAddr >> 16) & 0xFF);   /* 行地址周期3 */
    /* 发送读命令 (第二周期) */
    NAND_WRITE_CMD(NAND_CMD_READ2);
    /* 等待就绪 */
    NANDWaitReady();
    /* 读取数据 */
    for(i = 0; i < len; i++)
    {
        buffer[i] = NAND_READ_DATA();
    }
}
/* 写入页面数据 */
void NANDWritePage(unsigned int pageAddr, unsigned char *buffer, unsigned int len)
{
    unsigned int i;
    /* 发送页编程命令 */
    NAND_WRITE_CMD(NAND_CMD_PROGRAM1);
    /* 发送地址 */
    NAND_WRITE_ADDR(0x00);
    NAND_WRITE_ADDR(0x00);
    NAND_WRITE_ADDR((pageAddr >> 0) & 0xFF);
    NAND_WRITE_ADDR((pageAddr >> 8) & 0xFF);
    NAND_WRITE_ADDR((pageAddr >> 16) & 0xFF);
    /* 写入数据 */
    for(i = 0; i < len; i++)
    {
        NAND_WRITE_DATA(buffer[i]);
    }
    /* 发送编程确认命令 */
    NAND_WRITE_CMD(NAND_CMD_PROGRAM2);
    /* 等待完成 */
    NANDWaitReady();
}
/* 擦除块 */
void NANDEraseBlock(unsigned int blockAddr)
{
    /* 发送擦除命令 */
    NAND_WRITE_CMD(NAND_CMD_ERASE1);
    /* 发送块地址 (3个地址周期) */
    NAND_WRITE_ADDR((blockAddr >> 0) & 0xFF);
    NAND_WRITE_ADDR((blockAddr >> 8) & 0xFF);
    NAND_WRITE_ADDR((blockAddr >> 16) & 0xFF);
    /* 发送擦除确认命令 */
    NAND_WRITE_CMD(NAND_CMD_ERASE2);
    /* 等待完成 */
    NANDWaitReady();
}
void EMIFInit(void)
{
    /* 使能EMIFA模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_EMIFA, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
    /* 配置EMIF异步CS3时序 */
    /* 适用于大多数NAND Flash芯片 */
    HWREG(SOC_EMIFA_0_REGS + EMIFA_ASYNC_WAITCYCLE_CONFIG) = 0x80;
    HWREG(SOC_EMIFA_0_REGS + EMIFA_ASYNC_CS3_CR) =
        (0 << 31) |      /* SS=0 (异步模式) */
        (0 << 30) |      /* EW=0 (8位数据总线) */
        (5 << 26) |      /* W_SETUP = 5 */
        (10 << 20) |     /* W_STROBE = 10 */
        (2 << 17) |      /* W_HOLD = 2 */
        (5 << 13) |      /* R_SETUP = 5 */
        (10 << 7) |      /* R_STROBE = 10 */
        (2 << 4) |       /* R_HOLD = 2 */
        (1 << 0);        /* TA = 1 */
}
int main(void)
{
    unsigned char id[5];
    unsigned char writeBuf[256];
    unsigned char readBuf[256];
    unsigned int i;
    EMIFInit();
    /* 复位NAND */
    NAND_WRITE_CMD(NAND_CMD_RESET);
    NANDWaitReady();
    /* 读取Flash ID */
    NANDReadID(id);
    /* 初始化测试数据 */
    for(i = 0; i < 256; i++)
        writeBuf[i] = i;
    /* 擦除第一个块 */
    NANDEraseBlock(0);
    /* 写入数据到页面0 */
    NANDWritePage(0, writeBuf, 256);
    /* 读取数据 */
    NANDReadPage(0, readBuf, 256);
    /* 验证数据 */
    for(i = 0; i < 256; i++)
    {
        if(readBuf[i] != writeBuf[i])
        {
            /* 数据错误 */
            while(1);
        }
    }
    /* 测试通过 */
    while(1);
}

16. EMIF时钟配置

16.1 PLL0配置

PLL0时钟结构
 

 
晶振 (24MHz)
    ↓
PLL0 倍频 (×19)
    ↓
PLL0_SYSCLK1 (456MHz) ─→ CPU核心
    ↓ ÷2
PLL0_SYSCLK2 (228MHz)
    ↓ ÷4
PLL0_SYSCLK3 (114MHz) ─→ EMIF时钟
    ↓ ÷4
PLL0_SYSCLK4 (114MHz)

16.2 时钟计算公式

 

 
// PLL0倍频
PLL0_SYSCLK1 = 晶振频率 × (PLLM + 1)
             = 24MHz × (18 + 1)
             = 24MHz × 19
             = 456MHz
// EMIF时钟
PLL0_SYSCLK3 = PLL0_SYSCLK1 ÷ (PLLDIV3 + 1)
             = 456MHz ÷ (3 + 1)
             = 456MHz ÷ 4
             = 114MHz

16.3 PLL寄存器配置

PLLDIVx寄存器格式
// 寄存器格式
Bit 15: DxEN (分频器使能, 必须设为1)
Bit 4-0: RATIO (分频比, 实际分频=RATIO+1)

// 示例
PLL0_PLLDIV3 = 0x8003;
// → DxEN = 1 (使能)
// → RATIO = 3 (实际分频 = 4)
// → SYSCLK3 = 456MHz / 4 = 114MHz

16.4 修改EMIF时钟

方法1: 修改GEL文件 (仿真)
Set_Core_456MHz() {
    // 原配置: PLLDIV3=3 → 114MHz
    device_PLL0(0, 18, 0, 0, 1, 3, 9);

    // 修改为: PLLDIV3=5 → 76MHz
    device_PLL0(0, 18, 0, 0, 1, 5, 9);
}
方法2: 运行时修改
void ChangeEMIFClock(uint32_t divider) {
    // 等待PLL空闲
    while(PLL0_PLLSTAT & 0x1);

    // 设置新的分频值
    PLL0_PLLDIV3 = 0x8000 | (divider - 1);

    // 触发更新
    PLL0_PLLCMD |= 0x1;  // 设置GOSET位

    // 等待完成
    while(PLL0_PLLSTAT & 0x1);  // 等待GOSTAT清零
}

// 使用示例
ChangeEMIFClock(6);  // 456MHz/6 = 76MHz
ChangeEMIFClock(8);  // 456MHz/8 = 57MHz

16.5 常用EMIF时钟频率

目标频率分频值PLLDIV3计算
114MHz43456/4
91.2MHz54456/5
76MHz65456/6
65.1MHz76456/7
57MHz87456/8
50.7MHz98456/9

16.6 时钟测量验证

OBSCLK输出配置
 

 
void ConfigOBSCLK(void) {
    // 选择PLL0_SYSCLK3作为输出源
    HWREG(SOC_SYSCFG_0_REGS + SYSCFG_CFGCHIP3) =
        (0x17 << 0) |    // OCSEL = 0x17 (PLL0_SYSCLK3)
        (0 << 8) |       // OCSRC = PLL0
        (25 << 16);      // OSCDIV = 25 (实际分频=26)
}
// 输出频率验证
// OBSCLK = 114MHz / 26 = 4.4MHz
// 用示波器测量OBSCLK引脚即可验证

16.7 完整应用示例

 

 
/****************************************************************************/
/*                       EMIF时钟配置完整示例                                  */
/*               修改PLL0_SYSCLK3分频比来调整EMIF时钟频率                        */
/****************************************************************************/
#include "TMS320C6748.h"
#include "soc_C6748.h"
#include "hw_types.h"
/* PLL0寄存器地址 */
#define PLL0_BASE           0x01C11000
#define PLL0_PLLCTL         (PLL0_BASE + 0x100)
#define PLL0_PLLM           (PLL0_BASE + 0x110)
#define PLL0_PLLDIV3        (PLL0_BASE + 0x120)
#define PLL0_PLLCMD         (PLL0_BASE + 0x138)
#define PLL0_PLLSTAT        (PLL0_BASE + 0x13C)
#define PLL0_ALNCTL         (PLL0_BASE + 0x140)
/* SYSCFG寄存器 */
#define SYSCFG_BASE         0x01C14000
#define CFGCHIP3            (SYSCFG_BASE + 0x188)
/* 时钟频率常量 */
#define XTAL_FREQ           24000000    /* 晶振频率24MHz */
#define PLL0_SYSCLK1        456000000   /* CPU时钟456MHz */
/* 简单延时 */
void PLLDelay(unsigned int count)
{
    volatile unsigned int i;
    for(i = 0; i < count; i++);
}
/* 等待PLL状态稳定 */
void WaitPLLGoStatClear(void)
{
    while(HWREG(PLL0_PLLSTAT) & 0x01);  /* 等待GOSTAT位清零 */
}
/*
 * 修改EMIF时钟 (PLL0_SYSCLK3)
 * 参数: divider - 分频值 (1-32)
 * 结果: EMIF时钟 = 456MHz / divider
 *
 * 常用配置:
 *   divider=4 → 114MHz
 *   divider=6 → 76MHz
 *   divider=8 → 57MHz
 */
void SetEMIFClock(unsigned int divider)
{
    if(divider < 1) divider = 1;
    if(divider > 32) divider = 32;
    /* 等待PLL空闲 */
    WaitPLLGoStatClear();
    /* 设置新的分频值 */
    /* Bit 15 = DxEN (使能), Bit 4:0 = RATIO (实际分频 = RATIO + 1) */
    HWREG(PLL0_PLLDIV3) = 0x8000 | (divider - 1);
    /* 设置ALNCTL使分频器对齐 */
    HWREG(PLL0_ALNCTL) |= (1 << 2);  /* 使能SYSCLK3对齐 */
    /* 触发GO操作 */
    HWREG(PLL0_PLLCMD) |= 0x01;  /* 设置GOSET位 */
    /* 等待完成 */
    WaitPLLGoStatClear();
}
/* 获取当前EMIF时钟频率 */
unsigned int GetEMIFClock(void)
{
    unsigned int div3;
    div3 = HWREG(PLL0_PLLDIV3) & 0x1F;  /* 读取RATIO字段 */
    return PLL0_SYSCLK1 / (div3 + 1);
}
/* 配置OBSCLK输出用于测量验证 */
void ConfigOBSCLK(void)
{
    unsigned int cfgchip3;
    /* 读取当前配置 */
    cfgchip3 = HWREG(CFGCHIP3);
    /* 清除OCSEL字段 */
    cfgchip3 &= ~(0x1F << 0);
    /* 选择PLL0_SYSCLK3作为输出源 (OCSEL = 0x17) */
    cfgchip3 |= (0x17 << 0);
    /* 设置分频 (便于示波器测量) */
    cfgchip3 &= ~(0xFF << 16);
    cfgchip3 |= (25 << 16);  /* 分频26,输出约4.4MHz @ 114MHz */
    HWREG(CFGCHIP3) = cfgchip3;
}
int main(void)
{
    unsigned int emifClk;
    /* 读取当前EMIF时钟 */
    emifClk = GetEMIFClock();  /* 默认应该是114MHz */
    /* 配置OBSCLK用于测量 */
    ConfigOBSCLK();
    /* 示例: 降低EMIF时钟到76MHz */
    SetEMIFClock(6);  /* 456MHz / 6 = 76MHz */
    /* 验证新的时钟频率 */
    emifClk = GetEMIFClock();  /* 应该是76MHz */
    /* 示例: 恢复EMIF时钟到114MHz */
    SetEMIFClock(4);  /* 456MHz / 4 = 114MHz */
    emifClk = GetEMIFClock();  /* 应该是114MHz */
    while(1)
    {
        /* 可以用示波器测量OBSCLK引脚验证时钟频率 */
    }
}

附录A: 系统事件号

常用系统事件

事件号事件名称说明
1SYS_INT_NMI不可屏蔽中断
4SYS_INT_TIMER64P0_ALLTimer0全部中断
5SYS_INT_TIMER64P0_TINT12Timer0-12中断
6SYS_INT_TIMER64P0_TINT34Timer0-34中断
7SYS_INT_TIMER64P1_ALLTimer1全部中断
8SYS_INT_TIMER64P1_TINT12Timer1-12中断
9SYS_INT_TIMER64P1_TINT34Timer1-34中断
32SYS_INT_UART0_INTUART0中断
33SYS_INT_UART1_INTUART1中断
34SYS_INT_UART2_INTUART2中断
51SYS_INT_ECAP_SELECTECAP2中断
56SYS_INT_I2C0_INTI2C0中断
57SYS_INT_I2C1_INTI2C1中断
48SYS_INT_SPI0_INTSPI0中断
49SYS_INT_SPI1_INTSPI1中断
63SYS_INT_RTC_IRQSRTC中断
67SYS_INT_GPIO_B0INTGPIO Bank0中断
68SYS_INT_GPIO_B1INTGPIO Bank1中断
69SYS_INT_GPIO_B2INTGPIO Bank2中断
96SYS_INT_GPIO_B6INTGPIO Bank6中断

附录B: 常用基地址定义

 

 
// GPIO
#define SOC_GPIO_0_REGS              0x01E26000
// Timer
#define SOC_TMR_0_REGS               0x01C20000
#define SOC_TMR_1_REGS               0x01C21000
#define SOC_TMR_2_REGS               0x01D06000
#define SOC_TMR_3_REGS               0x01D07000
// UART
#define SOC_UART_0_REGS              0x01C42000
#define SOC_UART_1_REGS              0x01D0C000
#define SOC_UART_2_REGS              0x01D0D000
// I2C
#define SOC_I2C_0_REGS               0x01C22000
#define SOC_I2C_1_REGS               0x01E28000
// SPI
#define SOC_SPI_0_REGS               0x01C41000
#define SOC_SPI_1_REGS               0x01E12000
// EDMA3
#define SOC_EDMA3_CC_0_REGS          0x01C00000
#define SOC_EDMA3_TC_0_REGS          0x01C10000
// PWM
#define SOC_EPWM_0_REGS              0x01F00000
#define SOC_EPWM_1_REGS              0x01F02000
// ECAP
#define SOC_ECAP_0_REGS              0x01F06000
#define SOC_ECAP_1_REGS              0x01F07000
#define SOC_ECAP_2_REGS              0x01F08000
// RTC
#define SOC_RTC_0_REGS               0x01C23000
// EMIF
#define SOC_EMIFA_0_REGS             0x68000000
// 中断控制器
#define SOC_INTC_0_REGS              0x01800000
// 系统配置
#define SOC_SYSCFG_0_REGS            0x01C14000
// PSC (电源和睡眠控制器)
#define SOC_PSC_0_REGS               0x01C10000
#define SOC_PSC_1_REGS               0x01E27000
// PLL
#define SOC_PLL0_BASE                0x01C11000
#define SOC_PLL1_BASE                0x01E1A000

附录C: 快速参考表

C.1 中断优先级

优先级中断类型说明
1RESET复位
2NMI不可屏蔽中断
3Reserved保留
4INT4可屏蔽中断4
5INT5可屏蔽中断5
.........
15INT15可屏蔽中断15

C.2 GPIO引脚编号速查

 

 
GPIO引脚号 = Bank起始号 + 偏移
示例:
GPIO6[12] = 97 + 12 = 109
GPIO6[13] = 97 + 13 = 110
GPIO0[5]  = 1 + 5 = 6

C.3 时钟频率速查

时钟源默认频率用途
晶振24MHz输入时钟
PLL0_SYSCLK1456MHzCPU核心
PLL0_SYSCLK2228MHz外设
PLL0_SYSCLK3114MHzEMIF
PLL0_SYSCLK4114MHz-
PLL0_SYSCLK745.6MHzRMII
PLL1_SYSCLK1456MHzDDR
RTC时钟32KHz实时时钟

修订历史

版本日期说明
1.02026-01-03初始版本,包含16个模块的完整API

**文档结束**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值