NXP JN5169 使用硬件 SPI 从机收发数据
NXP JN5169使用硬件SPI从机收发数据
- 一、SPI 从机介绍
- 二、JN5169 从机代码
- 1、中断模式
- 2、轮询模式
- 三、STC15W408AS 主机代码
一、SPI 从机介绍
SPI 总线从接口允许 JN5169 与外围设备之间进行高速同步数据传输。 JN5169 作为 SPI 总线上的从设备运行,连接到 SPI 总线的外部设备作为主机。 引脚与 SPI 总线主接口不同,如下表所示:
SPI 总线采用简单的移位寄存器数据传输方案,SPISSEL 用作低电平有效选择控制。 数据以先进先出的方式移出和移入有源设备,从而允许 SPI 总线设备同时发送和接收数据。 主机输出从机输入或主机输入从机输出数据传输是相对于外部主机产生的时钟信号 SPISCLK 的。
SPI总线从机包括以下功能:
- 全双工同步数据传输
- 从机到外部时钟高达 8 MHz
- 支持8位传输(可先配置 MSB 或 LSB),每次传输之间 SPISSEL 均置为无效
- 内部 FIFO,最大 255 个字节,用于发送和接收
- 标准SPI总线模式 0; 数据在时钟正沿采样
- 可屏蔽中断,用于接收 FIFO 不为空,发送 FIFO 为空,接收 FIFO 填充水平高于阈值,发送 FIFO 低于阈值,发送 FIFO 溢出,接收 FIFO 下溢,发送 FIFO 下溢,接收超时
- 可编程的接收超时时间段允许生成一个中断,以提示如果在超时时间段内没有其他数据到达,则读取接收 FIFO
二、JN5169 从机代码
1、中断模式
#define MSB FALSE //spi从最高位开始传输
#define LSB TRUE //spi从最低位开始传输uint8 TxBuff[10]; //发送缓冲区
uint8 RxBuff[10]; //接收缓冲区void vCbSpiSlaveInt(uint32 u32Device, uint32 u32ItemBitmap)
{uint8 recv;if(E_AHI_DEVICE_SPIS == u32Device){ //SPI从机中断if((u32ItemBitmap & (1 << 0)) == E_AHI_SPIS_INT_RX_FIRST_MASK){vPrintf("数据已在接收FIFO中接收,以前是空的\n");}if((u32ItemBitmap & (1 << 1)) == E_AHI_SPIS_INT_TX_LAST_MASK){vPrintf("发送FIFO中的最后一个剩余字节已发送,缓冲区为空\n");}if((u32ItemBitmap & (1 << 2)) == E_AHI_SPIS_INT_RX_CLIMB_MASK){//这个中断提示应用从接收缓冲区中读取数据//等待一个读阈值中断或读超时中断,当出现其中一个中断时,将调用用户定义的回调函数来处理中断//函数 u8AHI_SpiSlaveRxReadByte()在这个回调函数中被调用。vPrintf("接收FIFO的填充级别已超过配置的阈值级别\n");recv = u8AHI_SpiSlaveRxReadByte();vPrintf("recv1 = %x\n", recv);recv = u8AHI_SpiSlaveRxReadByte();vPrintf("recv2 = %x\n", recv);}if((u32ItemBitmap & (1 << 3)) == E_AHI_SPIS_INT_TX_FALL_MASK){//等待一个写阈值中断来提示写入发送 FIFO//当出现这个中断时,将调用用户定义的回调函数来处理中断,vAHI_SpiSlaveTxWriteByte()在这个回调函数中被调用。//这个中断提示应用写数据到发送缓冲区//写入的字节数不应超出缓冲区大小减去缓冲区写阈值的结果。vPrintf("发送FIFO的填充水平已降至配置的阈值水平以下\n");vAHI_SpiSlaveTxWriteByte(0x99);}if((u32ItemBitmap & (1 << 4)) == E_AHI_SPIS_INT_RX_OVER_MASK){vPrintf("数据已接收但接收FIFO已满或繁忙(因此数据被丢弃)\n");}if((u32ItemBitmap & (1 << 5)) == E_AHI_SPIS_INT_TX_OVER_MASK){vPrintf("发送FIFO已写入但已满\n");}if((u32ItemBitmap & (1 << 6)) == E_AHI_SPIS_INT_RX_UNDER_MASK){vPrintf("接收FIFO已读取但为空\n");}if((u32ItemBitmap & (1 << 7)) == E_AHI_SPIS_INT_TX_UNDER_MASK){vPrintf("尝试发送但发送FIFO为空或未准备好(因此通过SPI总线发送了0x00)\n");}if((u32ItemBitmap & (1 << 8)) == E_AHI_SPIS_INT_RX_TIMEOUT_MASK){//等待一个读阈值中断或读超时中断,当出现其中一个中断时,将调用用户定义的回调函数来处理中断//函数 u8AHI_SpiSlaveRxReadByte()在这个回调函数中被调用。vPrintf("发生接收超时(在此期间未接收到其他数据)\n");recv = u8AHI_SpiSlaveRxReadByte();vPrintf("recv3 = %x\n", recv);}}
}PUBLIC void vSPI_Slave_Init()
{bAHI_SpiSlaveEnable(FALSE, //SPISMISO : DIO13, SPISMOSI : DIO12MSB, //高位开始传输TxBuff, //发送缓冲区sizeof(TxBuff), //发送缓冲区大小1, //发送缓冲区的填充阈值,以字节为单位(0到255),这个阈值提示当发送缓冲区数据大小这个阈值时,从机应当向主机写数据RxBuff, //接收缓冲区sizeof(RxBuff), //接收缓冲区大小1, //接收缓冲区的填充阈值,以字节为单位(0到255),这个阈值提示当接收缓冲区数据大小这个阈值时,应当向接收缓冲区读取数据100, //接收超时时间,以微秒为单位(0到4095)0x1FF //中断使能位,这里开启9个中断);vAHI_SpiSlaveRegisterCallback(vCbSpiSlaveInt);//注册中断回调函数//向发送缓冲区写入原始数据。//写入的字节数必须不能超过缓冲区的大小。//默认情况下,如果发送 FIFO 为空且传输由远程 SPI 主机启动,则 SPI 从机将发送数据字节 0x00。//由于设置发送缓冲区的填充阈值为1,所以每到主机向从机读取一次数据,从机向主机发送一个发送缓冲区的数据,直至发送缓冲区为空(先进先出)vAHI_SpiSlaveTxWriteByte(0x56);vAHI_SpiSlaveTxWriteByte(0x57);vAHI_SpiSlaveTxWriteByte(0x58);vAHI_SpiSlaveTxWriteByte(0x59);vAHI_SpiSlaveTxWriteByte(0x60);
}PUBLIC void AppColdStart(void)
{vAHI_WatchdogStop();(void) u32AHI_Init();vSPI_Slave_Init();vUartInit();vAHI_DelayXms(500);vPrintf("System init!\n");while (1) {}
}PUBLIC void AppWarmStart(void)
{AppColdStart();
}
效果图
2、轮询模式
#define MSB FALSE //spi从最高位开始传输
#define LSB TRUE //spi从最低位开始传输uint8 TxBuff[10];
uint8 RxBuff[10];PUBLIC void vSPI_Slave_Init()
{bAHI_SpiSlaveEnable(FALSE, //SPISMISO : DIO13, SPISMOSI : DIO12MSB, //高位开始传输TxBuff, //发送缓冲区sizeof(TxBuff), //发送缓冲区大小1, //发送缓冲区的填充阈值,以字节为单位(0到255),这个阈值提示当发送缓冲区数据大小这个阈值时,从机应当向主机写数据RxBuff, //接收缓冲区sizeof(RxBuff), //接收缓冲区大小1, //接收缓冲区的填充阈值,以字节为单位(0到255),这个阈值提示当接收缓冲区数据大小这个阈值时,应当向接收缓冲区读取数据100, //接收超时时间,以微秒为单位(0到4095)0x00 //中断使能位,这里关闭全部中断);//向发送缓冲区写入原始数据。//写入的字节数必须不能超过缓冲区的大小。//默认情况下,如果发送 FIFO 为空且传输由远程 SPI 主机启动,则 SPI 从机将发送数据字节 0x00。//由于设置发送缓冲区的填充阈值为1,所以每到主机向从机读取一次数据,从机向主机发送一个发送缓冲区的数据,直至发送缓冲区为空(先进先出)vAHI_SpiSlaveTxWriteByte(0x56);vAHI_SpiSlaveTxWriteByte(0x57);vAHI_SpiSlaveTxWriteByte(0x58);vAHI_SpiSlaveTxWriteByte(0x59);vAHI_SpiSlaveTxWriteByte(0x60);
}PUBLIC void AppColdStart(void)
{uint8 sta, len, recv;vAHI_WatchdogStop();(void) u32AHI_Init();vSPI_Slave_Init();vUartInit();vAHI_DelayXms(500);vPrintf("System init!\n");//实际运行时把串口打印注释掉while (1) {sta = u8AHI_SpiSlaveStatus();if((sta & 0x01) == E_AHI_SPIS_STAT_RX_AVAIL_MASK){ //接收缓冲区不为空len = u8AHI_SpiSlaveRxFillLevel();//vPrintf("接收缓冲区填充级别:%d\n", len);if((sta & 0x04) == E_AHI_SPIS_STAT_RX_ABOVE_MASK){ //接收缓冲区填充级别高于阈值//vPrintf("接收FIFO的填充级别已超过配置的阈值级别\n");recv = u8AHI_SpiSlaveRxReadByte();vPrintf("recv1 = %x\n", recv);}else{//vPrintf("接收FIFO的填充水平已降至配置的阈值水平以下\n");}}else{//vPrintf("接收缓冲区为空\n");}if((sta & 0x02) == E_AHI_SPIS_STAT_TX_PENDING_MASK){ //发送缓冲区不为空len = u8AHI_SpiSlaveTxFillLevel();//vPrintf("发送缓冲区填充级别:%d\n", len);if((sta & 0x08) == E_AHI_SPIS_STAT_TX_ABOVE_MASK){ //发送缓冲区填充级别高于阈值//vPrintf("发送缓冲区填充级别高于阈值\n");}else{//vPrintf("发送FIFO的填充水平已降至配置的阈值水平以下\n");vAHI_SpiSlaveTxWriteByte(0x99);}}else{//vPrintf("发送缓冲区为空\n");vAHI_SpiSlaveTxWriteByte(0x99);}}
}PUBLIC void AppWarmStart(void)
{AppColdStart();
}
效果图
三、STC15W408AS 主机代码
#define SPI_S0 0x04
#define SPI_S1 0x08#define SPIF 0x80 //SPSTAT.7
#define WCOL 0x40 //SPSTAT.6#define SSIG 0x80 //SPCTL.7
#define SPEN 0x40 //SPCTL.6
#define DORD 0x20 //SPCTL.5
#define MSTR 0x10 //SPCTL.4
#define CPOL 0x08 //SPCTL.3
#define CPHA 0x04 //SPCTL.2
#define SPDHH 0x00 //CPU_CLK/4
#define SPDH 0x01 //CPU_CLK/16
#define SPDL 0x02 //CPU_CLK/64
#define SPDLL 0x03 //CPU_CLK/128sbit SS = P1 ^ 2; //SPI_1的SS脚void InitSPI_1(void)
{ACC = P_SW1; //切换到第一组SPIACC &= ~(SPI_S0 | SPI_S1); //SPI_S0=0 SPI_S1=0P_SW1 = ACC; //(P1.2/SS, P1.3/MOSI, P1.4/MISO, P1.5/SCLK)// ACC = P_SW1; //可用于测试U7,U7使用的是第二组SPI控制Flash
// ACC &= ~(SPI_S0 | SPI_S1); //SPI_S0=1 SPI_S1=0
// ACC |= SPI_S0; //(P2.4/SS_2, P2.3/MOSI_2, P2.2/MISO_2, P2.1/SCLK_2)
// P_SW1 = ACC;// ACC = P_SW1; //切换到第三组SPI
// ACC &= ~(SPI_S0 | SPI_S1); //SPI_S0=0 SPI_S1=1
// ACC |= SPI_S1; //(P5.4/SS_3, P4.0/MOSI_3, P4.1/MISO_3, P4.3/SCLK_3)
// P_SW1 = ACC;SPDAT = 0; //初始化SPI数据SPSTAT = SPIF | WCOL; //清除SPI状态位SPCTL = SPEN | MSTR | SSIG | SPDHH; //主机模式
}uchar SPISwap(uchar dat)
{SPDAT = dat; //触发SPI发送数据while((SPSTAT & SPIF) != SPIF); //等待发送完成SPSTAT = SPIF | WCOL; //清除SPI状态位return SPDAT; //返回SPI数据
}uchar spi_send_byte(uchar dat)
{uchar recv = 0;SS = 0;recv = SPISwap(dat);SS = 1;return recv;
}void main(void)
{InitSPI_1();Init_Uart();EA = 1;Delay500ms();Delay500ms();printf("System init\r\n");while(1) {printf("recv = %x\r\n", spi_send_byte(0x56));Delay500ms();Delay500ms();Delay500ms();Delay500ms();}}
NXP JN5169 使用硬件 SPI 从机收发数据相关推荐
- 基础篇010.2 STM32驱动RC522 RFID模块之二:STM32硬件SPI驱动RC522
目录 1. 实验硬件及原理图 1.1 RFID硬件 1.2 硬件原理图 2. 单片机与RFID硬件模块分析 3. 利用STM32CubeMX创建MDK工程 3.1 STM32CubeMX工程创建 3. ...
- NXP iMX7 M4 核心 SPI Slave 测试
By Toradex秦海 1). 简介 在之前的两篇文章中已经介绍过基于NXP iMX7 异构多核架构进行开发调试,以及iMX7 M4核心PWM驱动开发.本文就继续演示基于iMX7 M4 SPI Sl ...
- NXP JN5169 读写片外 FLASH
NXP JN5169 读写片外 FLASH 一.原理图 二.读写兼容的片外 FLASH 设备 三.读写不兼容的片外 FLASH 设备 一.原理图 二.读写兼容的片外 FLASH 设备 JN5169 片 ...
- NXP JN5169使用定时器进行PWM输出和定时功能
NXP JN5169使用定时器进行PWM输出和定时功能 一.定时器介绍 1.定时器介绍 2.定时器可操作的模式 3.定时器DIO 4.定时器和PWM模式 5.定时器中断 二.实现代码 1.PWM输出 ...
- NXP JN5169 波特率配置方案
NXP JN5169 UART 波特率设置 一.系统时钟介绍 1.高速(32MHz)系统时钟 1.32MHz 晶体振荡器 2.高速RC振荡器 2.低速(32kHz)系统时钟 1.32 kHz RC 振 ...
- 【STM32】HAL库在7针脚0.96寸OLED屏上的移植---硬件SPI(一)
目录 SPI背景和接线 1.什么是SPI 2.如何接线 STM32CubeMX部分 1.配置时钟 2.配置SPI 3.工程生成 MDK 5 部分 1.移植OLED文件 2.修改引脚 3.修改main函 ...
- stm8 硬件SPI
第一步:stm8 SPI简介 在配置SPI相关寄存器时要注意时钟信号的相位和极性. 这次我们使用的是stm8驱动SO-8封装的DAC8830,使其输出一个方波. DAC8830引脚说明和时序: CS是 ...
- DSP28335的硬件SPI使用(无FIFO)总结
目录 前言 问题的提出 问题的解决 说在最后 前言 这两天折腾了一个旋变器解算模块的使用,类似于这种器件一般都是使用通信的方式写入芯片对应的寄存器的数据从而初始化芯片或得到可编程的结果:反之,我们也需 ...
- NXP JN5169 使用看门狗定时器
NXP JN5169 使用看门狗定时器 一.看门狗定时器介绍 二.示例代码 一.看门狗定时器介绍 JN5169 提供了看门狗定时器以防止软件锁定.它通过计算高速 RC 系统时钟(该振荡器运行在 27M ...
- NXP JN5169 UART 波特率设置
NXP JN5169 UART 波特率设置 一.系统时钟介绍 1.高速(32MHz)系统时钟 1.32MHz 晶体振荡器 2.高速RC振荡器 2.低速(32kHz)系统时钟 1.32 kHz RC 振 ...
最新文章
- 也谈架构:百万pv项目与虚拟化
- lodash源码分析之获取数据类型
- mysql进程内存不足_故障排除指南:MySQL的运行内存不足怎么办?
- apache服务器的配置文件httpd.conf中有很多内容,请解释如下配置项:
- Druid 配置_配置WebStatFilter
- Ubuntu16.04 下 tensorRT安装
- 用PD进行数据库建模经验总结
- java对象描述开车_java面向对象
- java中InvocationHandler 用于实现代理。
- 关于Vue SSR不可不知的问题
- MES生产管理系统中,看板管理究竟是什么
- opendevops_codo项目研究
- RocketMQ PERM含义 PERM=7、6、4、2
- Flutter 无埋点SDK实现
- 随机颜色十六进制(#ffffff)或rgb格式
- 绿皮书一些quant 题目 (1)
- 【005】舒曼的《梦幻曲》
- 【linux】循序渐进学运维-MySQL-SQL语句进阶
- Unity笔记——如何使怪物拥有警戒范围和攻击范围
- 网络编程基础【day09】:socket实现文件发送(六)