找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 560|回复: 6
打印 上一主题 下一主题
收起左侧

STC15与MAX31856的SPI读取全是0xFF

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


代码如下:
  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>P2.4///SPISS, P2.3/MOSI_2, P2.2/MISO_2, P2.1/SCLK_2</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, 下载次数: 5)

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:161164 发表于 2024-7-22 09:25 | 只看该作者


你没有置位SSIG
而且SS脚需要在读写前手动拉低


回复

使用道具 举报

板凳
ID:90212 发表于 2024-7-22 21:05 | 只看该作者
lkc8210 发表于 2024-7-22 09:25
你没有置位SSIG
而且SS脚需要在读写前手动拉低

按你所说,初始化忽略SS引脚,并把CS脚拉低(就一主一从),万用表测试也确实保持着0V,测试还是老样子。
  1. void InitSPI()
  2. {
  3.     ACC = P_SW1;                                //可用于测试U7,U7使用的是第二组SPI控制Flash
  4.     ACC &= ~(SPI_S0 | SPI_S1);                  //SPI_S0=1 SPI_S1=0
  5.     ACC |= SPI_S0;                              //(P2.4///SPISS, P2.3/MOSI_2, P2.2/MISO_2, P2.1/SCLK_2)
  6.     P_SW1 = ACC;  

  7.     SPDAT = 0;                  //初始化SPI数据  
  8.           SPSTAT = SPIF | WCOL;                       //清除SPI状态
  9.     SPISS = 0;//片选恒定拉低
  10.     SPCTL =  SPEN | MSTR| SSIG ;                 //设置SPI为主模式 忽略SS引脚

  11. }
复制代码



回复

使用道具 举报

地板
ID:430492 发表于 2024-7-23 08:52 | 只看该作者
如果不是硬件的SPI,那大概率是时序的问题。
回复

使用道具 举报

5#
ID:90212 发表于 2024-7-23 22:09 | 只看该作者
怀疑max31856板子故障,特意用Arduino mega2560搭了下,直接用现成的范例,软件spi,测试是正常的:



没接热电偶,直接短接可以读出冷端和0mv对应的温度:



回复

使用道具 举报

6#
ID:90212 发表于 2024-7-31 20:03 | 只看该作者
总算熬了几个夜搞清楚了,max31856规格书没认真看,以为跟以往一样下个范例改吧改吧就可以用了,其实好多案例都是害人的。






回复

使用道具 举报

7#
ID:938266 发表于 2024-10-13 12:57 | 只看该作者
gongzhu 发表于 2024-7-31 20:03
总算熬了几个夜搞清楚了,max31856规格书没认真看,以为跟以往一样下个范例改吧改吧就可以用了,其实好多案 ...

大佬,可以发一下您的代码吗,我最近也在调试这个模块测水温,但是测出来的温度误差很大
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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