找回密码
 立即注册
查看: 1978|回复: 7

请教,硬件SPI单主从通讯例程中的标志busy的用途

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:441
  • 最近打卡:2025-05-02 09:05:39

45

主题

176

回帖

1735

积分

金牌会员

积分
1735
发表于 2023-5-17 21:38:08 | 显示全部楼层 |阅读模式
本帖最后由 乐此不疲 于 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; //发送测试数据

}
}




回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6843

积分

论坛元老

积分
6843
发表于 2023-5-18 13:36:33 | 显示全部楼层
SPI是串行接口,发送一个字节的数据需要一位一位的发送,一个字节发送完成会产生中断标志,如果开了中断的话就会进入中断。
程序里发送数据前设置 busy = 1; 在发送完成中断里设置 busy = 0;
这样就可以通过判断 busy 值来确定写入 SPDAT 的数据是否发送完成,发送完成就可以发送下一个数据。
否则,如果没有发送完成就写入新的内容到 SPDAT 会产生覆盖导致数据丢失。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:441
  • 最近打卡:2025-05-02 09:05:39

45

主题

176

回帖

1735

积分

金牌会员

积分
1735
发表于 2023-5-18 19:03:38 | 显示全部楼层
乘风*** 发表于 2023-5-18 13:36
SPI是串行接口,发送一个字节的数据需要一位一位的发送,一个字节发送完成会产生中断标志,如果开了中断的 ...

多谢指点,因为我没有想到新旧数据的覆盖问题所以没能理解这个标志的意义,现在清楚了。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2023-5-18 21:48:03 | 显示全部楼层
如果么有busy标志,则一个数据还没发送完毕,又装下一个数据,最终乱套了。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:441
  • 最近打卡:2025-05-02 09:05:39

45

主题

176

回帖

1735

积分

金牌会员

积分
1735
发表于 2023-5-19 19:52:52 | 显示全部楼层
本帖最后由 乐此不疲 于 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以中断的方式来驱动这个屏幕,结果调试了很久也没能成功刷屏,请帮忙看看。
没有调试成功的代码如下:

  1. //====硬件SPI初始化函数=========================
  2. void spi_init()
  3. {
  4.     u8 n;
  5.     n = 2;                        //分频系数n取值0、1、2、3对应的时钟分频系数为:1/4、1/8、1/16、1/2
  6.     P_SW1|= 0x01<<2;//使用SPI通道2
  7.     P2PU = 0x2A;        //SDA、SCL、CS端口配置内部上拉电阻(4.1K)
  8.     P2M1 = 0x00;
  9.     P2M0 = 0x2A;
  10.     SPDAT = 0;                 //清空数据寄存器
  11.     SPSTAT = 0xC0;         //清除所有标志(共两个)
  12.     SPCTL = 0x9C|(n);//忽略SS、禁止SPI、高位先行、主机模式、时钟空闲时为高、上升沿(第二个边沿)采样、1/16时钟分频
  13.     IE2 = ESPI;
  14.     busy = 0;
  15.     cs = 1;
  16. }
  17. //====写8位数据函数============================
  18. //中断方式
  19. void SPI_WriteByte(u8 temp)
  20. {
  21.     SPI_Enable();                //使能硬件SPI
  22.     NOP1();
  23.     SPDAT = temp;         //发送数据
  24.     busy=1;                        //保持发送状态
  25.     while(busy);
  26.     /*
  27.             if(busy==0)                        //判断总线状态
  28.             {
  29.                     busy=1;                        //保持发送状态
  30.                     SPDAT = temp;         //发送数据
  31.             }
  32.             else
  33.             {
  34.                     sda=1;                        //释放总线
  35.                     scl=1;
  36.                 cs= 1;                        //挂断从机
  37.             }
  38.     */
  39. }
  40. //==============写指令函数======================
  41. void write_command(u8 comd)
  42. {
  43.     cs=0;                        //使能从机响应
  44.     sda=0;                        //D/CX=0(发送指令)
  45.     NOP1();
  46.     scl=0;                        //模拟一个下跳时钟脉冲
  47.     NOP1();                        //适当延时保障脉冲宽度
  48.     scl=1;                        //拉高时钟线恢复空闲状态
  49.     NOP1();
  50.     sda=1;                        //释放总线
  51.     SPI_WriteByte(comd);//使能硬件SPI发送一个字节
  52. }
  53. //==============写数据函数======================
  54. void write_data(u8 dat)
  55. {
  56.     cs=0;                        //使能从机响应
  57.     sda=1;                        //D/CX=1(发送数据)
  58.     NOP1();
  59.     scl=0;                        //模拟一个下跳时钟脉冲
  60.     NOP1();                        //适当延时保障脉冲宽度
  61.     scl=1;                        //拉高时钟线恢复空闲状态
  62.     NOP1();
  63.     SPI_WriteByte(dat);//使能硬件SPI发送一个字节
  64. }
  65. //====SPI中断函数=================================
  66. void SPI_Isr() interrupt 9
  67. {
  68.     busy=0;
  69.     SPSTAT = 0xc0; //中断发生时一个字节数据已经发送完毕、清中断标志等待下一次触发
  70.     SPI_Disable();//禁止硬件SPI
  71.     sda=1;
  72.     scl=1;
  73.     cs= 1;
  74. }
复制代码





点评

查询方式SPI都成功了,改SPI中断不应该有问题啊!  详情 回复 发表于 2023-5-19 21:33
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2023-5-19 21:33:14 | 显示全部楼层
乐此*** 发表于 2023-5-19 19:52
多谢指点,我用STC8H8K64U(开天斧实验板)做硬件SPI通讯测试时遇到一个问题,好几天没有理出头绪,希望帮忙 ...

查询方式SPI都成功了,改SPI中断不应该有问题啊!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:441
  • 最近打卡:2025-05-02 09:05:39

45

主题

176

回帖

1735

积分

金牌会员

积分
1735
发表于 2023-5-20 12:47:33 | 显示全部楼层
梁*** 发表于 2023-5-19 21:33
查询方式SPI都成功了,改SPI中断不应该有问题啊!

这几天就陷入到这里扑腾不出去了,我使用开天斧板子加这个彩屏的的实验计划是I/O模拟SPI、硬件SPI双字节发送、硬件查询1bit+SPI发送,硬件中断1bit+SPI发送、SPI-DMA发送,结果弄到这里就咋弄都不行了,而这段中断方式的代码如果发送一个字节数据时、用逻辑分析仪看时序波形也是没有问题的,但就是无法点亮屏幕,诡异!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-5-20 12:53:10 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 00:56 , Processed in 0.306200 second(s), 104 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表