打印
[STM32F1]

stm32f103zet6通过SPI1与max31865通信问题

[复制链接]
2131|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
护士姐姐控|  楼主 | 2020-5-1 18:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想通过STM32F103ZET6硬件SPI1与max31865通信 我找了好多资料 方法我能用的方法我都试过了 通过示波器和逻辑分析仪都能抓到发出的信号(MOSI)但是返回的信号就是无法收到正确的信号(MISO)  下面是一些关键的程序和配置 (我怕一大段一大段大家没心情看)
1、RCC配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
2、SCK、MOSI的GPIO模式设置为AF_PP,速度为50
3、MISO根据参考手册应设置为浮空输入或者上拉输入,我选择上拉输入IPU,速度50
4、CS使用D0来模拟,模式为OUT_PP速度50
5、SCK、MOSI、CS置位
7、SPI配置:
SPI_Direction_2Lines_FullDuplex;SPI_Mode_Master;SPI_DataSize_8b;SPI_CPOL_High;
SPI_CPHA_2Edge; SPI_NSS_Soft; SPI_BaudRatePrescaler_256;SPI_FirstBit_MSB;CRC设置为7(虽然在程序中没用,但是也设置了)
8、SPI_Cmd(SPI1, ENABLE);
9、我看到很多教程上都写了SPIRead(0XFF);这一步,我觉得没什么用
10、SPI读操作
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);          
        SPI_CS_LOW();
        SPI_I2S_SendData(SPI1, Address);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);       
        SPI_CS_HIGH();
        return SPI_I2S_ReceiveData(SPI1);

11、SPI写操作
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);          
        SPI_CS_LOW();
        SPI_I2S_SendData(SPI1, Address);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPI1, Message);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_CS_HIGH();

(以上两部其实很多教程都是这样)
12、主函数流程是SystemInit;SPI和GPIO配置(基本上就是上述的步骤只是多了几条必要的命令),申请了一个unsigned char类型得到data用于接收数据
13、配置MAX31865:具体流程就是向MAX31865的地址0x80写入0xc1,然后在0x00应该能够读取到刚刚写如的0xc1(这一步绝对不会错,我在stc15,树莓派上都已经成功了,不会有问题的)
14、不断循环13步(写配置,读配置)
我找不到问题,但是通过单步调试得到0xff(应该是0xc1),通过在程序中增加判断当data等于0xc1时亮灯,通过示波器(MOSI信号正常,MISO有一个固定的方波),通过逻辑分析仪(解码后MOSI正确,MISO受到0X00)都不能得到正确反馈。为了测试是不是STM32SPI波特率太快我在树莓派上将速度调整为500000,也能正确通信。查找网上资料,有人认为是CS信号太快不够稳定,我有尝试加过一定的延时,依旧无法通信。实在没办法我上某宝找人代做,对方不收,我已经黔驴技穷了,望大神们出手相助。跪谢了

使用特权

评论回复
沙发
willsonxie| | 2020-5-1 19:26 | 只看该作者
很简单,max31865的数据是16位的,你应该发16位,SPI_DataSize_16b,好好看看datasheet

使用特权

评论回复
板凳
护士姐姐控|  楼主 | 2020-5-1 19:28 | 只看该作者
本帖最后由 护士姐姐控 于 2020-5-1 19:36 编辑
willsonxie 发表于 2020-5-1 19:26
很简单,max31865的数据是16位的,你应该发16位,SPI_DataSize_16b,好好看看datasheet

我尝试过了 没有效果

使用特权

评论回复
地板
willsonxie| | 2020-5-1 19:30 | 只看该作者
就是要16个SCK

使用特权

评论回复
评论
护士姐姐控 2020-5-1 19:38 回复TA
一下摘自datesheet Communication is through eight 8-bit registers that contain conversion, status, and configuration data. All programming is done by selecting the appropriate address of the desired register location. Table 1 illustrates the addresses for the registers. 
5
willsonxie| | 2020-5-1 19:31 | 只看该作者
不能分为2次发八个

使用特权

评论回复
评论
护士姐姐控 2020-5-1 19:37 回复TA
是的 改为16B也是不起作用的 我尝试过了 
6
护士姐姐控|  楼主 | 2020-5-1 19:39 | 只看该作者

还有就是stc15 我使用的是8位也是能成功的

使用特权

评论回复
7
axbin| | 2020-5-1 22:13 | 只看该作者
本帖最后由 axbin 于 2020-5-22 13:36 编辑

----

使用特权

评论回复
8
护士姐姐控|  楼主 | 2020-5-1 22:20 | 只看该作者
axbin 发表于 2020-5-1 22:13
CS先设置HIGH了,怎么接收数据,另外内部上有40KΩ,会不会使数字信号变形呢 ...

在传输数据时会拉低的

使用特权

评论回复
9
axbin| | 2020-5-2 09:15 | 只看该作者
本帖最后由 axbin 于 2020-5-22 13:37 编辑
护士姐姐控 发表于 2020-5-1 22:20
在传输数据时会拉低的
return SPI_I2S_ReceiveData(SPI1)返回的是写入Address的同时得到的数据,不是写入Address后的数据,你需要再写入一个字节再读。SPI通讯每写入一个位都有一个位输出,写入Address的同时还不知道输出的数据代表什么。

使用特权

评论回复
10
雪山飞狐D| | 2020-5-2 12:03 | 只看该作者
    先用纯软件IO模拟SPI,成功通信了以后再对照硬件SPI,看看时序区别在哪里

使用特权

评论回复
11
zchong| | 2020-5-2 20:55 | 只看该作者
有逻辑分析仪和示波器还不好办吗?看波形看不出来有问题?

使用特权

评论回复
12
maximQ820270087| | 2020-5-3 12:19 | 只看该作者
MAX31865程序代码
主函数:
[cpp] view plain copy
1.        #include "stm32f10x.h"  
2.        #include "usart.h"  
3.        #include "max31865.h"  
4.        #include "HT1621.h"  
5.        #include "stm32f10x_gpio.h"  
6.        #include "spi.h"  
7.          
8.        extern uint8_t  Data_Buffer[8];   
9.        extern uint8_t DRDY_Status(void);  
10.        //extern void Inital_MAX31865(void) ;  
11.        extern uint8_t MAX31865_Config;   
12.          
13.          
14.         extern float Temperature;  
15.        int main(void)  
16.        {   
17.          
18.            GPIO_InitTypeDef GPIO_InitStructure;  
19.            RCC_DeInit();     
20.            //RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA , ENABLE);     
21.            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB , ENABLE);     
22.          
23.            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PA.8  
24.            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
25.            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽式输出  
26.            GPIO_Init(GPIOA, &GPIO_InitStructure);  
27.             
28.            //用PB0读取MAX31865的状态  
29.            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PB.0  
30.            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
31.            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;  //浮空输入  
32.            GPIO_Init(GPIOB, &GPIO_InitStructure);   
33.             
34.            uart_init(9600);  
35.            printf("\r\nDetect\r\n");     
36.             
37.            GPIO_ResetBits(GPIOA, GPIO_Pin_8);//set 0  
38.             
39.            delay_init();      
40.            ht1621_GPIO_Init();  
41.            ht1621_Init();  
42.            lcd_clear();//清屏  
43.             
44.          <span style="white-space:pre">  </span>SPI1_Init();  
45.            Max31865_Init();  
46.             
47.            while(1)  
48.            {  
49.                Temperature = Get_Temperature();  
50.                printf("temp=%f\r\n",Temperature);  
51.                ht1621_TempDisplay(Temperature);  
52.            }  
53.        }  

使用特权

评论回复
13
Prry| | 2020-5-4 13:43 | 只看该作者
1、一个读过程要保证CS一直拉低,直至读完成。
读过程:
CS拉低
写寄存器地址
读寄存器数据
CS拉高
2、看你代码,写寄存器地址后CS又拉高了,后面再去读数据。自然是无效。
3、SPIRead(0XFF),是有用的,spi是同步通信,时钟由主控产生,调用这句是让硬件spi产生时钟信号去读数据,填0xff或者0x00都可以,原则上与具体cpu硬件spi有关。

使用特权

评论回复
14
磨砂| | 2020-6-2 14:36 | 只看该作者
分成两次发送吗?

使用特权

评论回复
15
shengguochao| | 2020-6-4 08:45 | 只看该作者
搞定了吗!我项目用的是MAX31856,可以交流!

使用特权

评论回复
16
JIEMORANG| | 2021-11-11 16:39 | 只看该作者
1、MAX31856读温度命令是发送0x01后要发送连续发送3个0xff的无用信号来同步读温度数据,具体原因https://bbs.21ic.com/space-username-Prry.html 已经解释清楚了。
2、   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);         
        SPI_CS_LOW();
        SPI_I2S_SendData(SPI1, Address);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPI1, Message);
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        SPI_CS_HIGH();

这个写操作函数在写完数据后等待发送寄存器为空后马上拉高了片选,会造成数据写入失败,可以用示波器看看,会看到数据还没有发送完成片选就拉高了,应加1ms延时。

使用特权

评论回复
17
Draker| | 2022-4-2 09:38 | 只看该作者
解决了嘛?我也遇到同样的问题了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

6

帖子

0

粉丝