请教,硬件SPI单主从通讯例程中的标志busy的用途
本帖最后由 乐此不疲 于 2023-5-17 22:16 编辑请教各位管理员及各位大神,希望能指点一下,先谢了!
问题:我没能理解程序中的busy这个标志的用途是什么,在mcu主机与单个从机(单片机spi总线上仅有一个设备)通讯时没有这个标志会出现什么状况?
数据手册中的例程如下:
#include "stc8h.h"
#include "intrins.h"
sbit SS = P1^0;
sbit LED = P1^1;
bit busy;
void SPI_Isr() interrupt 9
{
SPSTAT = 0xc0; //清中断标志
SS = 1; //拉高从机的 SS 管脚
busy = 0;
LED = !LED; //测试端口
}
void main()
{
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;
busy = 0;
SPCTL = 0x50; //使能 SPI 主机模式
SPSTAT = 0xc0; //清中断标志
IE2 = ESPI; //使能 SPI 中断
EA = 1;
while (1)
{
while (busy);
busy = 1;
SS = 0; //拉低从机 SS 管脚
SPDAT = 0x5a; //发送测试数据
}
}
SPI是串行接口,发送一个字节的数据需要一位一位的发送,一个字节发送完成会产生中断标志,如果开了中断的话就会进入中断。
程序里发送数据前设置 busy = 1; 在发送完成中断里设置 busy = 0;
这样就可以通过判断 busy 值来确定写入 SPDAT 的数据是否发送完成,发送完成就可以发送下一个数据。
否则,如果没有发送完成就写入新的内容到 SPDAT 会产生覆盖导致数据丢失。 乘风飞扬 发表于 2023-5-18 13:36
SPI是串行接口,发送一个字节的数据需要一位一位的发送,一个字节发送完成会产生中断标志,如果开了中断的 ...
多谢指点,因为我没有想到新旧数据的覆盖问题所以没能理解这个标志的意义,现在清楚了。 如果么有busy标志,则一个数据还没发送完毕,又装下一个数据,最终乱套了。 本帖最后由 乐此不疲 于 2023-5-19 21:19 编辑
梁工 发表于 2023-5-18 21:48
如果么有busy标志,则一个数据还没发送完毕,又装下一个数据,最终乱套了。 ...
多谢指点,我用STC8H8K64U(开天斧实验板)做硬件SPI通讯测试时遇到一个问题,好几天没有理出头绪,希望帮忙看看我的代码哪里弄错了,先谢了!
我实验用到TFT-LCD的驱动是ILI9481,他是三线SPI,要求数据中包含一位指令/数据(D/CX控制)的命令,也就是传输的字节为9位的数据,我曾经在本坛发帖分享过用硬件SPI以查询方式每次发送两个字节的方法的驱动方法,原帖:开天斧三.1板测试——硬件SPI驱动三线SPI_TFT屏(代码分享)https://www.stcaimcu.com/forum.php?mod=viewthread&tid=1091(出处: 国芯论坛-STC全球32位8051爱好者互助交流社区)
此贴之后我又实验了I/0模拟输出一个脉冲+以查询方式发送8位字节数据的模式,实验也很成功,在时钟设定为40mhz状态下刷屏很爽很稳定。接下来我继续测试用硬件SPI以中断的方式来驱动这个屏幕,结果调试了很久也没能成功刷屏,请帮忙看看。
没有调试成功的代码如下:
//====硬件SPI初始化函数=========================
void spi_init()
{
u8 n;
n = 2; //分频系数n取值0、1、2、3对应的时钟分频系数为:1/4、1/8、1/16、1/2
P_SW1|= 0x01<<2;//使用SPI通道2
P2PU = 0x2A; //SDA、SCL、CS端口配置内部上拉电阻(4.1K)
P2M1 = 0x00;
P2M0 = 0x2A;
SPDAT = 0; //清空数据寄存器
SPSTAT = 0xC0; //清除所有标志(共两个)
SPCTL = 0x9C|(n);//忽略SS、禁止SPI、高位先行、主机模式、时钟空闲时为高、上升沿(第二个边沿)采样、1/16时钟分频
IE2 = ESPI;
busy = 0;
cs = 1;
}
//====写8位数据函数============================
//中断方式
void SPI_WriteByte(u8 temp)
{
SPI_Enable(); //使能硬件SPI
NOP1();
SPDAT = temp; //发送数据
busy=1; //保持发送状态
while(busy);
/*
if(busy==0) //判断总线状态
{
busy=1; //保持发送状态
SPDAT = temp; //发送数据
}
else
{
sda=1; //释放总线
scl=1;
cs= 1; //挂断从机
}
*/
}
//==============写指令函数======================
void write_command(u8 comd)
{
cs=0; //使能从机响应
sda=0; //D/CX=0(发送指令)
NOP1();
scl=0; //模拟一个下跳时钟脉冲
NOP1(); //适当延时保障脉冲宽度
scl=1; //拉高时钟线恢复空闲状态
NOP1();
sda=1; //释放总线
SPI_WriteByte(comd);//使能硬件SPI发送一个字节
}
//==============写数据函数======================
void write_data(u8 dat)
{
cs=0; //使能从机响应
sda=1; //D/CX=1(发送数据)
NOP1();
scl=0; //模拟一个下跳时钟脉冲
NOP1(); //适当延时保障脉冲宽度
scl=1; //拉高时钟线恢复空闲状态
NOP1();
SPI_WriteByte(dat);//使能硬件SPI发送一个字节
}
//====SPI中断函数=================================
void SPI_Isr() interrupt 9
{
busy=0;
SPSTAT = 0xc0; //中断发生时一个字节数据已经发送完毕、清中断标志等待下一次触发
SPI_Disable();//禁止硬件SPI
sda=1;
scl=1;
cs= 1;
}
乐此不疲 发表于 2023-5-19 19:52
多谢指点,我用STC8H8K64U(开天斧实验板)做硬件SPI通讯测试时遇到一个问题,好几天没有理出头绪,希望帮忙 ...
查询方式SPI都成功了,改SPI中断不应该有问题啊! 梁工 发表于 2023-5-19 21:33
查询方式SPI都成功了,改SPI中断不应该有问题啊!
这几天就陷入到这里扑腾不出去了,我使用开天斧板子加这个彩屏的的实验计划是I/O模拟SPI、硬件SPI双字节发送、硬件查询1bit+SPI发送,硬件中断1bit+SPI发送、SPI-DMA发送,结果弄到这里就咋弄都不行了,而这段中断方式的代码如果发送一个字节数据时、用逻辑分析仪看时序波形也是没有问题的,但就是无法点亮屏幕,诡异! 使用开天斧板子====你先用仿真来调试
STC8H8K64U自带硬件USB直接仿真步骤 - 编译器/仿真器/ISP下载/做自己的ISP/ID号加密/程序加密后传输 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
页:
[1]