有个关于DMA_SPI的问题
照着手册写了个小例子,功能是用DMA_SPI把一个数组中的数据发送出去,想问一下启动DMA SPI后需要为SPDAT赋值一次是正常的吗?代码如下:
#include <STC/STC8H.H>
#include <intrins.h>
#ifdef _VSCODE
#define INTERRUPT(n)
#define bit char
#else
#define INTERRUPT(n) interrupt n
#endif
typedef unsigned char u8;
typedef unsigned int u16;
#define SS P10 // SS管脚
#define LED P11 // 测试用灯
bit fg_spi_busy; // spi忙碌标识
char fg_spi_dma_idel; // dma spi空闲标识
u8 xdata buf[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; // 数据缓冲区
#define BUF_LENG sizeof(buf) / sizeof(u8); // 缓冲区字节数
void spi_init()
{
SPCTL = 0x50;// 使能SPI、设置为主机模式
SPSTAT = 0xc0; // 清理中断标志、写冲突标识
IE2 = 0X02; // 使能SPI中断
}
void dma_spi_init()
{
DMA_SPI_CFG |= 0X80; // 使能DMA_SPI中断
DMA_SPI_CFG |= 0X40; // 允许DMS_SPI发送数据
DMA_SPI_CFG &= ~0X20; // 禁止DMS_SPI接收数据
DMA_SPI_CR |= 0X80; // 使能SPI_DMA功能
DMA_SPI_STA = 0; // 清理中断、数据覆盖、数据丢弃标识
DMA_SPI_AMT = BUF_LENG - 1; // 设置需要传输的字节数
DMA_SPI_TXA = buf; // 设置需要传输的数据的地址
DMA_SPI_CFG2 = 0; // SS脚控制
}
// 启动DMA_SPI主机模式
void dma_spi_host_start()
{
DMA_SPI_CR |= 0X40;
}
// 启动DMA_SPI从机模式
void dma_spi_cclent_start()
{
DMA_SPI_CR |= 0X20;
}
void main_init()
{
P_SW2 |= 0x80; // 允许使用XFR
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LED = 1;
SS = 1;
fg_spi_busy = 0;
fg_spi_dma_idel = 1;
spi_init();
dma_spi_init();
EA = 1;
}
// 通过SPI发送1个字节数据
void spi_send(u8 c)
{
while (fg_spi_busy)
;
fg_spi_busy = 1;
SS = 0; // 拉低从机 SS管脚
SPDAT = c; // 发送测试数据
}
// char i = 0;
void main()
{
main_init();
while (1)
{
if (fg_spi_dma_idel)
{
LED = 1; // 熄灯
fg_spi_dma_idel = 0;// 设置为忙碌
dma_spi_host_start(); // 开始工作
SPDAT = 0; // 需要触发一次SPI//???
}
}
}
// SPI中断服务
void spi_main() INTERRUPT(9)
{
SPSTAT = 0xc0; // 清清中断标志等
SS = 1; // 拉高SS
fg_spi_busy = 0; // 不再忙碌
// LED = !LED; // 闪烁
}
// DMA中断服务 这段代码需要拓展中断的辅助
void spi_dma_main(void) INTERRUPT(13)
{
if (DMA_SPI_STA & 0x04) // SPI_DMA 中断
{
DMA_SPI_STA &= ~0x04; // 清除标识
fg_spi_dma_idel = 1;// 发送完毕,设置为空闲
LED = 0; // 亮灯
}
// 每批次触发一次
}
关于DMASPI的使用,您提出的问题非常具有代表性。在使用DMASPI进行数据传输时,是否需要在启动后为SPDAT寄存器赋值一次,取决于具体的硬件设计和DMA配置方式。
从您的代码来看,您已经对SPI和DMASPI进行了基本初始化,并定义了数据缓冲区buf。在DMA模式下,通常由DMA控制器自动处理数据的搬运,而无需手动干预SPDAT寄存器。然而,在某些情况下,特别是在DMA配置未完全自动化的系统中,可能需要在DMA启动前对SPDAT进行一次赋值,以确保DMA能够正确地将数据发送出去。
这种情况是正常的,尤其是在以下几种情形中:
1. DMA通道尚未完成初始化:在DMA通道启动之前,如果SPDAT没有被正确设置,DMA可能会读取到无效或默认值,导致数据传输错误。
2. DMA触发条件依赖于SPDAT状态:有些系统要求在DMA启动前,SPDAT必须包含第一个数据字节,以便DMA可以开始传输。
3. DMA工作模式为“单次传输”:在这种模式下,DMA可能仅传输一次,因此需要在启动前准备好初始数据。
综上所述,在DMASPI启动后为SPDAT赋值一次是正常且合理的操作,特别是在DMA配置尚未完全自动化的情况下。建议您根据具体芯片手册中的DMASPI相关章节进行确认,并结合实际测试验证数据传输的正确性。
如需进一步优化代码或调试问题,可提供更多关于DMA配置和中断处理的细节。
[本文内容由国芯人工智能辅助生成,仅供参考] 设置模式,复位FIFO和指针,设置地址和长度,启动DMA就行了,为什么要赋值SPDAT
使用DMA操作SPI就不需要再软件操作SPI了
DebugLab 发表于 2025-7-26 13:41
设置模式,复位FIFO和指针,设置地址和长度,启动DMA就行了,为什么要赋值SPDAT
使用DMA操作SPI就不需要再 ...
我把启动方法改了,然后注释掉了mian()里面的SPDAT = 0,结果没看到波形出来,保留SPDAT = 0就有,另外看手册上说的FIFO是接收数据用的吧,我只发送数据也要清理它吗?
// 启动DMA_SPI主机模式
void dma_spi_host_start()
{
DMA_SPI_TXA = buf; // 设置需要传输的数据的地址
DMA_SPI_AMT = BUF_LENG - 1; // 设置需要传输的字节数
DMA_SPI_CR |= 0x01; // 清理FIFO
DMA_SPI_CR |= 0X40; // 启动
}
SSIG 一般配1。
可以参考库函数DMA例程
https://www.stcaimcu.com/data/do ... 1U-SOFTWARE-LIB.zip ercircle 发表于 2025-7-26 15:27
SSIG 一般配1。
可以参考库函数DMA例程
牛逼{:4_250:}修改SPCTL = 0xD0;之后就可以注释到SPDAT=0;这句了。
页:
[1]