请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:EK-TM4C123GXL 主题中讨论的其他器件:TM4C123
您好!
我目前使用 Tiva 器件实现音频回放功能、使用 PWM 信号、其中音频文件存储在 Booster Pack 上的外部闪存中。 到目前为止、我已配置 SSI 模块从闪存中读取数据并成功回放。 但是、接下来、我想使用 uDMA 来处理从闪存到缓冲器、然后到 PWM 输出的计时器的数据传输。
这一问题与 CS 信号有关。 在数据传输期间、它必须为低电平、在 tm4c123器件上、这只能通过切换 GPIO 引脚手动完成。 我在下面添加了两个使用的文件。 同样、我希望了解一些有关如何为该函数实施 UDMA 的见解或潜在示例。
谢谢、
Garrett
*timers.c*
#define SSI_CLK GPIO_PIN_4 #define SSI_CS GPIO_PIN_5 #define SSI_RX GPIO_PIN_6 #define SSI_TX GPIO_PIN_7 #define endAddr 208065 int d=0、c=10、b=0; int strAddr = 100; uint8_t Buffer[10]; long duty0x764 、0x5932、无符号正弦、0x7D39、0x4039 0x7FFD、0x0647、0xBA33、0x0000、0x45CD、 0xF9B9、 0x8003、0xBF8D、0xA69C、0x8028、0x82C7、 0x0000、0x7D39、0x7FD8、0x5964、0x4073、 0x7FFD、 0x0647、0xBA33、0x0000、0x45CD、0xF9B9、 0x8003、0xBF8D、0xA69C、0x8028、0x82C7}; 无符号短整型 sine1[32]={0x0000、0x007A、0x007D、0x0057、0x003F、 0x007D、0x06、0x00B6、0x0000、0x0044、 0x00F4、 0x007D、0x00BB、0x00A3、0x007D、0x0080、 0x0000、0x007A、0x007D、0x0057、0x003F、 0x007D、 0x0006、0x00B6、0x0000、0x0044、0x00F4、 0x007D、0x00BB、0x00A3、0x007D、0x0080}; // // //! \addtogroup example_list //!计时器(计时器)
//! //! 此示例应用演示了如何使用计时器来生成 //! 周期性中断。 一个计时器设置为每秒中断一次和 //! 另一个中断每秒中断两次;每个中断处理程序将切换 //! 显示屏上有自己的指示灯。 //// ***************** //uint32_t g_ui32Flags; //********* // //如果驱动程序库遇到错误,则调用的错误例程。 //// ***************** #ifdef debug void __error__(char *dpcFilename、uint32_t ui32Line) { #endif //********* // // Timer 3和 SSI 的中断处理程序 // //********* void Timer3IntHandler (void) { ROM_TimerIntClear (TIMER3_base、TIMER_CAPB_EVENT); if (c=10){ SPIFlashRead (SSI2_base、strAddr、&Buffer、10); if (strAddr >= endAddr) strAddr = 100; 其他 strAddr=strAddr+10; C=0; } ROM_TimerMatchSet (TIMER3_base、TIMER_A、Buffer[c]); C++; /* ROM_TimerIntClear (TIMER3_base、TIMER_CAPB_EVENT); ROM_TimerMatchSet (TIMER3_base、TIMER_A、sine1[d]); D++; 如果(d ==32) D = 0; * } //********* // //此示例应用演示了如何使用计时器生成 //周期性中断。 //// ***************** int main (void) { 无符号超长整型 PeriodA; 无符号长整型 ulPeriodB; unsigned long sysClock; uint8_t manID = 0; uint16_t DevID = 0; ulPeriodA = 255;//最大65535、16位定时器 设置为16kHz (80MHz/5000) dutyCycle = 1;//50%占空比 ulPeriodB = 4080;//(66.66M / 16k) //启用使用的外设 ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC); ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER3); ROM_SysCtlPeripheralEnable (sysctl_Periph_SSI2); ////////////////////////////////////////////////////////////////////////////////// 引脚配置//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //计时器3A ROM_GPIOPinConfigure (GPIO_PB2_T3CCP0); //配置 GPIO 引脚的功能(_P#_fucnion) ROM_GPIOPinTypeTimer (GPIO_PORTB_BASE、GPIO_PIN_2); //配置引脚以供计时器使用 //音频放大器 ROM_GPIOPinTypeGPIOOutput (GPIO_PORTB_BASE、GPIO_PIN_3);//使用板载 AMP CTL* ROM_GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_3、0); //必须移动电阻器才能使用 AMP CTL (PA4) //SSI ROM_GPIOPinTypeSSI (GPIO_PORTB_BASE、SSI_CLK | SSI_RX | SSI_TX);//配置 SSI 的引脚 ROM_GPIOPinTypeGPIOOutput (GPIO_Porta_base、GPIO_PIN_3);//手动 CS ROM_GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_3、255);//手动芯片选择 ROM_GPIOPinConfigure (GPIO_PB4_SSI2CLK); // ROM_GPIOPinConfigure (GPIO_PB5_SSI2FSS); ROM_GPIOPinConfigure (GPIO_PB6_SSI2RX); ROM_GPIOPinConfigure (GPIO_PB7_SSI2TX); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// 定时器配置////////////////////////////////////////////////////////////////////////////////////////// //66.66MHz 系统时钟 ROM_SysCtlClockSet (SYSCTL_SYSDIV_3 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz); //配置16位 PWM 计时器 ROM_TimerConfigure (TIMER3_base、(TIMER_CFG_SPLIT_PAGE|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM)); //计时器3A 加载、匹配、控制 ROM_TimerLoadSet (TIMER3_base、TIMER_A、ulPeriodA); //从'load value' ulPeriod 递减计数 ROM_TimerMatchSet (TIMER3_base、TIMER_A、dutyCycle); ///PWM 高电平、直到计数器达到匹配值 ROM_TimerControlLevel (TIMER3_base、TIMER_A、true); //控制输出电平=> true =低电平有效输出 // Timer 3B 装载、匹配、控制 ROM_TimerLoadSet (TIMER3_base、TIMER_B、ulPeriodB); //从'load value' ulPeriod 递减计数 ROM_TimerMatchSet (TIMER3_base、TIMER_B、dutyCycle); ///PWM 高电平、直到计数器达到匹配值 ROM_TimerControlLevel (TIMER3_base、TIMER_B、true); //控制输出电平=> true =低电平有效输出 //计数器中断 TimerUpdateMode (TIMER3_base、TIMER_B、TIMER_UP_LOAD_TIMEOUT | TIMER_UP_MATH_TIMEOUT); ROM_TimerIntEnable (TIMER3_base、TIMER_CAPB_EVENT); //启用计时器。 ROM_TimerEnable (TIMER3_base、TIMER_A); ROM_TimerEnable (TIMER3_base、TIMER_B); //启用处理器中断。 ROM_IntMasterEnable(); //设置计时器超时的中断。 ROM_IntEnable (INT_TIMER3B); //////////////////////////////////////////////////////////////////// SSI 配置////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sysClock = ROM_SysCtlClockGet (); // SSIConfigSetExpClk (SSI2_base、sysClock、SSI_FRF_MOTO_MOTO_0、SSI_MODE_MASTER、2000000、 8); // SSIAdvModeSet (SSI2_base、SSI_ADV_MODE_READ_WRITE);//从从从器件写入/读取数据的模式 // SSIAdvFrameHoldEnable (SSI2_base); //启用帧保持功能 // SSIEnable (SSI2_base); //启用 SPI 模块 SPIFlashInit (SSI2_base、sysClock、4000000); // SPIFlashReadID (SSI2_base、&manID、&DevID); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //uint32_t data[4]; while (1)//在计时器运行时永久循环。 {
}
* spi_flash.c*
void SPIFlashInit (uint32_t ui32Base、uint32_t ui32Clock、uint32_t ui32BitRate) { // //配置 SPI 模块。 // MAP_SSIConfigSetExpClk (ui32Base、ui32Clock、SSI_FRF_MOTO_MODE_0、 SSI_MODE_MASTER、ui32BitRate、8); // //启用高级操作模式,默认为读/写模式。 // MAP_SSIAdvModeSet (ui32Base、SSI_ADV_MODE_READ_WRITE); // //启用帧保持功能。 // // map_SSIAdvFrameHoldEnable (ui32Base); // //启用 SPI 模块。 // MAP_SSIEnable (ui32Base); } void SPIFlashRead (uint32_t ui32Base、uint32_t ui32Addr、uint8_t * pui8Data、 uint32_t ui32Count) { uint32_t ui32废物桶; uint8_t c=0; // //从接收 FIFO 中漏掉任何剩余数据。 // while (map_SSIDataGetNonBlocking (ui32Base、&ui32Trash)!= 0) { } ROM_GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_3、0);//手动芯片选择//手动 C //SysCtlDelay (10); //将 SSI 模块设置为只写模式。 MAP_SSIAdvModeSet (ui32Base、SSI_ADV_MODE_WRITE); // //发送读取命令。 // MAP_SSIDataPut (ui32Base、CMD_READ); ui32Addr=ui32Addr-4; // //发送要读取的第一个字节的地址 // MAP_SSIDataPut (ui32Base、(ui32Addr >> 16)& 0xff); MAP_SSIDataPut (ui32Base、(ui32Addr >> 8)& 0xff); MAP_SSIDataPut (ui32Base、ui32Addr & 0xff); // //将 SSI 模块设置为读/写模式。 在此模式下、虚拟写入是 //需要进行传输;SPI 闪存将忽略 //数据。 // MAP_SSIAdvModeSet (ui32Base、SSI_ADV_MODE_READ_WRITE); // //查看是否有一个字节要读取。 // for (c = 0;c <= 4;c++) { MAP_SSIDataPut (ui32Base、241); MAP_SSIDataGet (ui32Base、&ui32Addr); } if (ui32Count = 1) { // //执行单个虚拟写入,将其标记为帧的末尾。 // MAP_SSIDataPut (ui32Base、241); } 其他 { // //执行虚拟写入以使循环初始化。 // MAP_SSIDataPut (ui32Base、241); // //在剩余要读取的字节超过一个时循环。 // while (--ui32Count!= 1) { // //执行虚拟写入以防止发送 FIFO 运行 //空。 // MAP_SSIDataPut (ui32Base、241); //- //从接收 FIFO 读取下一个数据字节并将其放入 //数据缓冲区。 // MAP_SSIDataGet (ui32Base、\ui32Addr); *pui8Data++= ui32Addr & 0xff; } // //执行最终虚拟写入,将其标记为帧的末尾。 // MAP_SSIDataPut (ui32Base、241); // //从接收 FIFO 读取下一个数据字节并将其放入 //数据缓冲区。 // MAP_SSIDataGet (ui32Base、\ui32Addr); *pui8Data++= ui32Addr & 0xff; } // //从接收 FIFO 读取最终数据字节并将其放入 //数据缓冲区。 // MAP_SSIDataGet (ui32Base、\ui32Addr); *pui8Data++= ui32Addr & 0xff; while (SSIBusy (SSI2_base)){} ROM_GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_3、255);//手动芯片选择 }