使用 ENC28J60 + UIP 实现 UDP 数据的收发,其中ENC28J60 通过 SPI 接口和单片机连接;在收发数据的时候,要先对 ENC28J60 的寄存器进行读写,然后才写入或者读取要收发的数据。 读写寄存器的时候,开启了 SPI 的片选,只需要读取 1 到 2 个字节的数据;在正式读写收发的数据的时候,开启 SPI 片选需要读写多个字节的数据。 这样的情况下如何配置DMA,如果在开启片选信号的时候开启DMA,关闭片选信号的情况下关闭DMA;在进行寄存器读写的时候,岂不是会出现频繁开关DMA的情况,这样算不算降低了程序的执行效率,而且还增加了程序的不稳定性? 我想在进行寄存器读写的时候,单独使用SPI,不使能DMA,在传输数据的时候,再开启DMA,请问这样配置合理吗?或者说还有无其他的实现方式? 读写寄存器部分代码: /********************************************* 函数名:ENC28J60_ReadOp 功 能:从器件寄存器读取状态 形 参:op--操作码 address--控制寄存器地址 返回值:寄存器状态值 备 注:命令时序图--29页 **********************************************/ uint8_t ENC28J60_ReadOp(uint8_t op, uint8_t address) { uint8_t dat = 0; CS_L; dat = op | (address & ADDR_MASK); //重构操作码和地址,参见手册第28页。 SPI_ReadWrite(dat); dat = SPI_ReadWrite(0xFF); //如果需要,进行虚拟读取(对于MAC和MII,请参见手册第29页) /* 如果是MAC和MII寄存器,第一个读取的字节无效,该信息包含在地址的最高位 */ if(address & 0x80) { dat = SPI_ReadWrite(0xFF); } CS_H; return dat; } /********************************************* 函数名:ENC28J60_WriteOp 功 能:向器件寄存器写入1byte 形 参:op--操作码 address--控制寄存器地址 data--数据字节 **********************************************/ void ENC28J60_WriteOp(uint8_t op, uint8_t address, uint8_t data) { uint8_t dat = 0; CS_L; dat = op | (address & ADDR_MASK);//重构操作码和地址,参见手册第28页。 SPI_ReadWrite(dat); SPI_ReadWrite(data);//写入数据 CS_H; } 读写数据部分代码: /********************************************* 函数名:ENC28J60_ReadBuffer 功 能:读取缓冲存储器的数据 形 参:len--长度 data--存放数据的指针 **********************************************/ void ENC28J60_ReadBuffer(uint32_t len, uint8_t* data) { CS_L; SPI_ReadWrite(ENC28J60_READ_BUF_MEM); while(len) { len--; *data = (uint8_t)SPI_ReadWrite(0); data++; } *data = '\0'; CS_H; } /********************************************* 函数名:ENC28J60_WriteBuffer 功 能:向缓冲存储器写入数据 形 参:len--字节长度 data--数据内容的指针 **********************************************/ void ENC28J60_WriteBuffer(uint32_t len, uint8_t* data) { CS_L; SPI_ReadWrite(ENC28J60_WRITE_BUF_MEM); while(len) { len--; SPI_ReadWrite(*data); data++; } CS_H; } |
外部中断升降沿类型判断
STM32G0B1adc+dma采样数据错位
STM32H7打开DCache后,串口1DMA接受数据位空
定时器正交编码器功能
STM32F427串口接收和发送中断同时使能,出现接收中断丢数的现象。
为什么生成代码时一直卡在generating user source code 救救孩子吧。
STM32 SPI从机用DMA方式实现全双工,数据传输过程中出错。
关于VN9D5D20F芯片的SPI 的信号脚SDO设计疑问
easylogger打印失败
为什么ETH配置中没有Advanced Parameters?
==>片选你可以使用STM32 SPI外设的NSS脚或者另外单独拉一个GPIO来完成。你希望每次单独做不同长度的读取,这是没问题的。对于片选脚,想通信时就先拉低,通信完毕拉高即可。当然,如果使用NSS,交由硬件管理也可以。
这样的情况下如何配置DMA,如果在开启片选信号的时候开启DMA,关闭片选信号的情况下关闭DMA;在进行寄存器读写的时候,
岂不是会出现频繁开关DMA的情况,这样算不算降低了程序的执行效率,而且还增加了程序的不稳定性?
==》
DMA配置其实只关心触发源,目的地,源端地,传输长度,再就是传输模式。
鉴于你目前应用,你这里配置为Normal模式合适,传输长度你具体启动SPI的DMA收发时给定。每完成启动一轮SPI收发后DMA会自行停止,
无须手动干预。这样使用谈不上降低程序执行效率或增加不稳定性。
我想在进行寄存器读写的时候,单独使用SPI,不使能DMA,在传输数据的时候,再开启DMA,请问这样配置合理吗?或者说还有无其他的实现方式?
==》
也是可以的。你现在配置DMA为Normal模式,不想使用DMA时,基于查询或中断方式进行SPI收发也可以。说不上什么不合理,但似乎没有
什么必要,反正DMA都配置好,随时待命了。
本来发布了,刚刚看发现只文章居然是空白的,然后就把内容补上去了,顺带修改了一下题目.
OK,简单交流下。
片选可以使用STM32 SPI模块的片选脚,或者单拉一个GPIO也行。你这里的SPI_READWRITE换成相应SPI库函数,并使用DMA模式。 当然,你要在SPI配置那里使能SPI的DMA收发配置。你这里len对应 SPI DMA收发API函数里的size,如果只读写1个数据,size就是1。
显然,当你把SPI收发换成DMA方式后,代码会更简洁些。效率也会更高。
STM32各个系列的Cube库里都有关于SPI的基本例程,可以参考,尤其看懂那几个基本的收发API函数。