一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 6123|回复: 11
收起左侧

STC15与MAX31856的SPI读取全是0xFF

[复制链接]
发表于 2024-7-22 08:37 | 显示全部楼层 |阅读模式
淘的一个max31856现成的模块,附送了Arduino范例和一个FreeRTOS的范例,恰恰对这两个很陌生,便根据max31856文档改成了STC15的第二组spi接口,4线制(P2.4///SPISS, P2.3/MOSI_2, P2.2/MISO_2, P2.1/SCLK_2)。
无论用stcisp中stc15的spi单主单从范例,还是虚拟spi,读出的寄存器值都是0xFF(255)。
可以确定接线没问题,如果接线错误读出的就是0x00。
原理图

max31856

max31856

代码如下:
  1. //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
  2. //若无特别说明,工作频率一般为11.0592MHz
  3. #include "reg51.h"
  4. #include<stdio.h>
  5. #include<intrins.h>

  6. #define FOSC        11059200UL
  7. #define BAUD        115200

  8. typedef unsigned char BYTE;
  9. typedef unsigned int WORD;
  10. typedef unsigned char u8;
  11. typedef unsigned int u16;

  12. #define SR_Read 0x0F
  13. #define     URMD    0           //0:使用定时器2作为波特率发生器
  14. //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
  15. //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器
  16. sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
  17. sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
  18. sfr P0M1 = 0x93;
  19. sfr P0M0 = 0x94;
  20. sfr P2M1 = 0x95;
  21. sfr P2M0 = 0x96;
  22. sfr P3M1 = 0xB1;
  23. sfr P3M0 = 0xB2;
  24. sfr P4M1 = 0xB3;
  25. sfr P4M0 = 0xB4;
  26. sfr P5M1 = 0xC9;
  27. sfr P5M0 = 0xCA;
  28. sfr P6M1 = 0xCB;
  29. sfr P6M0 = 0xCC;
  30. sfr P7M1 = 0xE1;
  31. sfr P7M0 = 0xE2;
  32. sfr T2H   = 0xd6;               //定时器2高8位
  33. sfr T2L   = 0xd7;               //定时器2低8位

  34. sfr  AUXR           =   0x8e;                   //辅助寄存器
  35. sfr P_SW1           =   0xa2;                   //外设功能切换寄存器1
  36. #define SPI_S0 0x04             //P_SW1.2
  37. #define SPI_S1 0x08             //P_SW1.3

  38. sfr SPSTAT      =   0xcd;       //SPI状态寄存器
  39. #define SPIF        0x80        //SPSTAT.7                                
  40. #define WCOL        0x40        //SPSTAT.6                                
  41. sfr SPCTL       =   0xce;       //SPI控制寄存器
  42. #define SSIG        0x80        //SPCTL.7                                 
  43. #define SPEN        0x40        //SPCTL.6                                 
  44. #define DORD        0x20        //SPCTL.5                                 
  45. #define MSTR        0x10        //SPCTL.4                                 
  46. #define CPOL        0x08        //SPCTL.3                                 
  47. #define CPHA        0x04        //SPCTL.2                                 
  48. #define SPDHH       0x00        //CPU_CLK/4                              
  49. #define SPDH        0x01        //CPU_CLK/16                              
  50. #define SPDL        0x02        //CPU_CLK/64                              
  51. #define SPDLL       0x03        //CPU_CLK/128                             
  52. sfr SPDAT       =   0xcf;       //SPI数据寄存器
  53. sbit SPISS      =   P2 ^ 4;     //SPI从机选择口, 连接到其它MCU的SS口
  54. //当SPI为一主多从模式时,请使用主机的普通IO口连接到从机的SS口

  55. sfr IE2         =   0xAF;       //中断控制寄存器2
  56. #define ESPI        0x02        //IE2.1
  57. void InitUart();
  58. void InitSPI();

  59. u16 WenDu;
  60. u8 WenDu_Time, Error;
  61. BYTE SPISwap(BYTE dat);
  62. u8 SPI_RW_Reg(u8 reg, u8 value);
  63. ///////////////////////////////////////////////////////////
  64. void Delay500ms(void)        //@11.0592MHz
  65. {
  66.     unsigned char data i, j, k;
  67.     _nop_();
  68.     _nop_();
  69.     i = 22;
  70.     j = 3;
  71.     k = 227;
  72.     do
  73.     {
  74.         do
  75.         {
  76.             while (--k);
  77.         }
  78.         while (--j);
  79.     }
  80.     while (--i);
  81. }

  82. void main()
  83. {
  84.     u16 x, y;
  85.     P0M0 = 0x00;
  86.     P0M1 = 0x00;
  87.     P1M0 = 0x00;
  88.     P1M1 = 0x00;
  89.     P2M0 = 0x00;
  90.     P2M1 = 0x00;
  91.     P3M0 = 0x00;
  92.     P3M1 = 0x00;
  93.     P4M0 = 0x00;
  94.     P4M1 = 0x00;
  95.     P5M0 = 0x00;
  96.     P5M1 = 0x00;
  97.     P6M0 = 0x00;
  98.     P6M1 = 0x00;
  99.     P7M0 = 0x00;
  100.     P7M1 = 0x00;

  101.     InitUart();                 //初始化串口
  102.     InitSPI();                  //初始化SPI
  103.     IE2 |= ESPI;
  104.     EA = 1;
  105.     while (1)
  106.     {
  107.         Delay500ms()        ;
  108.         x = SPISwap(0x00);//00~0F 都是只读配置reg
  109.         y = SPISwap(0x01);
  110.         printf("MAX31856_Read00:%d ;Read01:%d\n", x, y);
  111.     }
  112. }

  113. BYTE SPISwap(BYTE dat)
  114. {
  115.     SPDAT = dat;                //触发SPI发送数据
  116.     while (!(SPSTAT & SPIF));   //等待发送完成
  117.     SPSTAT = SPIF | WCOL;       //清除SPI状态位
  118.     return SPDAT;               //返回SPI数据
  119. }
  120. //SPI写寄存器
  121. //reg:指定寄存器地址
  122. //value:写入的值
  123. u8 SPI_RW_Reg(u8 reg, u8 value)
  124. {
  125.     u8 status;
  126.     status = SPISwap(reg); //返回从MISO读出的数据,status应为上次向该寄存器内写的value
  127.     SPISwap(value);        //写入寄存器的值
  128.     return status;       // 返回状态值
  129. }
  130. ///////////////////////////////////////////////////////////
  131. void InitUart()
  132. {
  133.     SCON = 0x5a;                //设置串口为8位可变波特率
  134. #if URMD == 0
  135.     T2L = (65536 - (FOSC / 4 / BAUD));
  136.     T2H = (65536 - (FOSC / 4 / BAUD)) >> 8;
  137.     AUXR = 0x14;                //T2为1T模式, 并启动定时器2
  138.     AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
  139. #elif URMD == 1
  140.     AUXR = 0x40;                //定时器1为1T模式
  141.     TMOD = 0x00;                //定时器1为模式0(16位自动重载)
  142.     TL1 = (65536 - (FOSC / 4 / BAUD));
  143.     TH1 = (65536 - (FOSC / 4 / BAUD)) >> 8;
  144.     TR1 = 1;                    //定时器1开始启动
  145. #else
  146.     TMOD = 0x20;                //设置定时器1为8位自动重装载模式
  147.     AUXR = 0x40;                //定时器1为1T模式
  148.     TH1 = TL1 = (256 - (FOSC / 32 / BAUD));
  149.     TR1 = 1;
  150. #endif
  151. }
  152. ///////////////////////////////////////////////////////////
  153. void InitSPI()
  154. {
  155.     ACC = P_SW1;                                //可用于测试U7,U7使用的是第二组SPI控制Flash
  156.     ACC &= ~(SPI_S0 | SPI_S1);                  //SPI_S0=1 SPI_S1=0
  157.     ACC |= SPI_S0;                              //<b><font color="#ff00ff">(P2.4///SPISS, P2.3/MOSI_2, P2.2/MISO_2, P2.1/SCLK_2)</font></b>
  158.     P_SW1 = ACC;

  159.     SPDAT = 0;                  //初始化SPI数据
  160.     SPSTAT = SPIF | WCOL;                       //清除SPI状态
  161.     SPCTL =  SPEN | MSTR;                 //设置SPI为主模式
  162.     //SPCTL = SPEN | MSTR | SSIG | SPDLL;        //主机模式 忽略SS引脚
  163. }
复制代码
有没遇到同类问题的高手请指点一下。
原软件和资料包:
MAX31856模块资料.zip (1.47 MB, 下载次数: 1)

发表于 2024-7-22 17:43 | 显示全部楼层
spi频率多少?

点评

4个频率都试过,一样的结果: #define FOSC 11059200UL #define SPDHH 0x00 //CPU_CLK/4 #define SPDH 0x01 //CPU_CLK/16  详情 回复 发表于 2024-7-22 21:21
 楼主| 发表于 2024-7-22 21:21 | 显示全部楼层

4个频率都试过,一样的结果:

#define FOSC        11059200UL
#define SPDHH       0x00        //CPU_CLK/4                              
#define SPDH        0x01        //CPU_CLK/16                              
#define SPDL        0x02        //CPU_CLK/64                              
#define SPDLL       0x03        //CPU_CLK/128   

点评

没用过这个芯片,用过6675,好像要先初始化。  详情 回复 发表于 2024-7-23 18:44
发表于 2024-7-23 18:44 | 显示全部楼层
gongzhu 发表于 2024-7-22 21:21
4个频率都试过,一样的结果:

#define FOSC        11059200UL

没用过这个芯片,用过6675,好像要先初始化。

点评

不管是否需要初始化,它0x00~0xF0是配置寄存器,有默认值是可以读取的  详情 回复 发表于 2024-7-23 22:55
发表于 2024-7-23 18:56 | 显示全部楼层
如果手头有arduino先用它试试。

点评

用Mega 2560测试,直接用现成的范例正常:[attachimg]461844[/attachimg] 没外接热电偶,直接短接测0mV的温度和读取冷端温度都正常: [attachimg]461845[/attachimg]  详情 回复 发表于 2024-7-23 22:52
 楼主| 发表于 2024-7-23 22:52 | 显示全部楼层
fujiachun 发表于 2024-7-23 18:56
如果手头有arduino先用它试试。

用Mega 2560测试,直接用现成的范例正常: 2024-07-23_220513.png

没外接热电偶,直接短接测0mV的温度和读取冷端温度都正常:
2024-07-23_220432.png
 楼主| 发表于 2024-7-23 22:55 | 显示全部楼层
fujiachun 发表于 2024-7-23 18:44
没用过这个芯片,用过6675,好像要先初始化。

不管是否需要初始化,它0x00~0xF0是配置寄存器,有默认值是可以读取的
发表于 2024-7-24 00:15 | 显示全部楼层
没用过,乱猜,不一定正确哈。代码有点多,没细看。
spi 的片选 cs 通常作为流程开始结束的标志。好像没看到操作片选

点评

搞定了,软件spi还没搞定。 硬件SPI读取时,必须要读空字节: 原来 u8 buffer=SpiShift(addr); 是错误的!  详情 回复 发表于 2024-7-29 22:33
CS是一个原因,现在把CS一直拉低也不行(只有一个从机设备)。  详情 回复 发表于 2024-7-28 09:57
 楼主| 发表于 2024-7-28 09:57 | 显示全部楼层
treeyan 发表于 2024-7-24 00:15
没用过,乱猜,不一定正确哈。代码有点多,没细看。
spi 的片选 cs 通常作为流程开始结束的标志。好像没看 ...

CS是一个原因,现在把CS一直拉低也不行(只有一个从机设备)。
 楼主| 发表于 2024-7-29 22:33 | 显示全部楼层
treeyan 发表于 2024-7-24 00:15
没用过,乱猜,不一定正确哈。代码有点多,没细看。
spi 的片选 cs 通常作为流程开始结束的标志。好像没看 ...

搞定了,软件spi还没搞定。
硬件SPI读取时,必须要读空字节:
原来 u8 buffer=SpiShift(addr); 是错误的!
  1. void SPIRead(u8 addr, u8 siz, u8 *buffer)
  2. {
  3.     SS = 0;
  4.     SpiShift(addr);           //发送地址
  5.     while (siz)
  6.     {
  7.         *buffer = SpiShift(0);     //自动连续读,必须以空字节形式读
  8.         buffer++;
  9.         siz--;
  10.     }
  11.     SS = 1;
  12. }
复制代码


本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-4-28 05:31 , Processed in 0.050889 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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