基于CSDN博客系列文章整理 整理日期:2026-01-03
目录
示例总结表
| 模块 | 示例内容 |
|---|---|
| 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与EEPROM | AT24C02单字节/页读写完整示例 |
| 9. EDMA+SPI Flash | W25Q16 Flash读写+扇区擦除示例 |
| 10. PWM(eHRPWM)模块 | 10kHz PWM+占空比调节+死区控制示例 |
| 11. ECAP_APWM模式 | ECAP辅助PWM+占空比渐变示例 |
| 12. 看门狗定时器 | 5秒超时+喂狗操作完整示例 |
| 13. NMI不可屏蔽中断 | 紧急数据保存+安全模式示例 |
| 14. RTC实时时钟 | 时间设置+闹钟+每秒中断示例 |
| 15. EMIF访问NAND Flash | NAND 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] | 1 | GPIO0[0] = 1 |
| GPIO1[0] | 17 | GPIO1[0] = 17 |
| GPIO6[0] | 97 | GPIO6[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, ¶mSet);
}
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 看门狗密钥
| 密钥值 | 状态转换 |
|---|---|
| 0xA5C6 | Active → Service (喂狗第1步) <br> 或 Initial → Pre-Active (激活第1步) |
| 0xDA7E | Pre-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 | 普通中断 |
|---|---|---|
| 可屏蔽 | ❌ 不可屏蔽 | ✅ 可屏蔽 |
| 中断号 | 固定为1 | 4-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命令集
| 命令 | 代码 | 说明 |
|---|---|---|
| Read | 0x00 → 0x30 | 读页面 (两周期命令) |
| Program | 0x80 → 0x10 | 编程页面 |
| Erase | 0x60 → 0xD0 | 擦除块 |
| Read ID | 0x90 | 读取芯片ID |
| Reset | 0xFF | 复位Flash |
| Read Status | 0x70 | 读状态寄存器 |
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 | 计算 |
|---|---|---|---|
| 114MHz | 4 | 3 | 456/4 |
| 91.2MHz | 5 | 4 | 456/5 |
| 76MHz | 6 | 5 | 456/6 |
| 65.1MHz | 7 | 6 | 456/7 |
| 57MHz | 8 | 7 | 456/8 |
| 50.7MHz | 9 | 8 | 456/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: 系统事件号
常用系统事件
| 事件号 | 事件名称 | 说明 |
|---|---|---|
| 1 | SYS_INT_NMI | 不可屏蔽中断 |
| 4 | SYS_INT_TIMER64P0_ALL | Timer0全部中断 |
| 5 | SYS_INT_TIMER64P0_TINT12 | Timer0-12中断 |
| 6 | SYS_INT_TIMER64P0_TINT34 | Timer0-34中断 |
| 7 | SYS_INT_TIMER64P1_ALL | Timer1全部中断 |
| 8 | SYS_INT_TIMER64P1_TINT12 | Timer1-12中断 |
| 9 | SYS_INT_TIMER64P1_TINT34 | Timer1-34中断 |
| 32 | SYS_INT_UART0_INT | UART0中断 |
| 33 | SYS_INT_UART1_INT | UART1中断 |
| 34 | SYS_INT_UART2_INT | UART2中断 |
| 51 | SYS_INT_ECAP_SELECT | ECAP2中断 |
| 56 | SYS_INT_I2C0_INT | I2C0中断 |
| 57 | SYS_INT_I2C1_INT | I2C1中断 |
| 48 | SYS_INT_SPI0_INT | SPI0中断 |
| 49 | SYS_INT_SPI1_INT | SPI1中断 |
| 63 | SYS_INT_RTC_IRQS | RTC中断 |
| 67 | SYS_INT_GPIO_B0INT | GPIO Bank0中断 |
| 68 | SYS_INT_GPIO_B1INT | GPIO Bank1中断 |
| 69 | SYS_INT_GPIO_B2INT | GPIO Bank2中断 |
| 96 | SYS_INT_GPIO_B6INT | GPIO 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 中断优先级
| 优先级 | 中断类型 | 说明 |
|---|---|---|
| 1 | RESET | 复位 |
| 2 | NMI | 不可屏蔽中断 |
| 3 | Reserved | 保留 |
| 4 | INT4 | 可屏蔽中断4 |
| 5 | INT5 | 可屏蔽中断5 |
| ... | ... | ... |
| 15 | INT15 | 可屏蔽中断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_SYSCLK1 | 456MHz | CPU核心 |
| PLL0_SYSCLK2 | 228MHz | 外设 |
| PLL0_SYSCLK3 | 114MHz | EMIF |
| PLL0_SYSCLK4 | 114MHz | - |
| PLL0_SYSCLK7 | 45.6MHz | RMII |
| PLL1_SYSCLK1 | 456MHz | DDR |
| RTC时钟 | 32KHz | 实时时钟 |
修订历史
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.0 | 2026-01-03 | 初始版本,包含16个模块的完整API |
**文档结束**

309

被折叠的 条评论
为什么被折叠?



