你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

(源码)STM32模拟SPI实现不同工作模式的问题

[复制链接]
xiajintaord 提问时间:2018-8-10 11:58 /
本帖最后由 xiajintaord 于 2018-8-10 15:12 编辑

现在做的一个项目,由于成本原因,选用的芯片的SPI数量不够实现产品的功能,所以需要一个软件模拟的 SPI;
今天上午参考论坛里的帖子实现了 SPI 工作模式0 的代码,测试通过了(说明IO配置没有问题)。现在在调试工作模式1的代码,无法通讯,时序始终不对,代码帖出来,大家看看。
现在的问题就是工作模式1的时序怎么实现了。
补充一下:用的 keil 开发的寄存器版本,上传的代码格式有问题,上图片看吧。
  1. #include <stm32l1xx.h>

  2. #define SPI_SCLK_SET                {GPIOB->BSRRL=0x00000040;}        //PB6
  3. #define SPI_SCLK_CLR                {GPIOB->BSRRH=0x00000040;}      
  4. #define SPI_MOSI_SET                {GPIOB->BSRRL=0x00000080;}        //PB7
  5. #define SPI_MOSI_CLR                {GPIOB->BSRRH=0x00000080;}
  6. #define SPI_MISO_DAT                (GPIOB->IDR&0x00000008)             //PB3  



  7. void SPI_Delay(uint16 n)
  8. {
  9.          n<<=4;
  10.          while(n--);
  11. }
复制代码

模拟SPI0.png 模拟SPI1.png
收藏 2 评论15 发布时间:2018-8-10 11:58

举报

15个回答
xiajintaord 最优答案 回答时间:2018-8-14 15:17:59
结贴:
00 01工作模式的模拟 SPI 已经调试完成了,都在下面的附件里面;
大家基本上用的都是硬件的 SPI,但有时候受限于成本,硬件资源不足的情况下,像 IIC 一样软件模拟的 SPI 也是一个不错的选择啊。
仅仅是修改部分代码,主要是针对 SCLK 时序,要理解 SPI 在不同的工作模式下的数据收发时序;

simulate_spi.rar

下载

895 Bytes, 下载次数: 87, 下载积分: ST金币 -1

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3 结帖奖励

查看全部评分

xiajintaord 回答时间:2018-8-10 14:54:04
本帖最后由 xiajintaord 于 2018-8-10 15:15 编辑
toofree 发表于 2018-8-10 14:20
不知道你的IO读写是怎么来的。

请参考IO模拟I2C的代码,如下:

感谢回复。
说明一下,我这个是用的 L1 系列,BSRR 寄存器可以分别向 BSRRH、BSRRL 写1进行清零或者置位对应的 IO 口,另外,上面工作模式 0 的代码已经测试通过了,说明 IO 配置是 OK 的。
寄存器定义头文件.png
BSRR.png


现在的问题是,工作模式 1 的时序没模拟出来,正在用示波器调试,还需要改改程序逻辑
七哥 回答时间:2018-8-10 14:20:08
不知道你的IO读写是怎么来的。

请参考IO模拟I2C的代码,如下:
#define SCL_H         GPIOB->BSRR = GPIO_Pin_6
#define SCL_L         GPIOB->BRR  = GPIO_Pin_6
   
#define SDA_H         GPIOB->BSRR = GPIO_Pin_7
#define SDA_L         GPIOB->BRR  = GPIO_Pin_7

#define SCL_read      GPIOB->IDR  & GPIO_Pin_6
#define SDA_read      GPIOB->IDR  & GPIO_Pin_7

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

CC4 回答时间:2018-8-10 15:12:20
toofree 发表于 2018-8-10 14:20
不知道你的IO读写是怎么来的。

请参考IO模拟I2C的代码,如下:

这个代码是如何配置IIC的SDA端口方向的??
xiajintaord 回答时间:2018-8-10 15:14:37
select326 发表于 2018-8-10 15:12
这个代码是如何配置IIC的SDA端口方向的??

像这种一般都会在程序初始化的时候配置输入输出模式的,这里指关心 IO 的输入输出寄存器的值
七哥 回答时间:2018-8-10 15:16:17
xiajintaord 发表于 2018-8-10 14:54
感谢回复。
说明一下,我这个是用的 L1 系列,BSRR 寄存器可以分别向 BSRRH、BSRRL 写1进行清零或者置位 ...

不清楚你说的模式0是什么?官方没有这种叫法。
只有master mode、Slave mode、TI mode、BIDIMODE=1、BIDIMODE=0

既然模式0通过,那么模式1也应该能通过的。好好抠一下协议

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

dengdenghui 回答时间:2018-8-10 15:35:12
可以问一下啥编辑软件嘛这个配色很舒服
xiajintaord 回答时间:2018-8-10 17:25:43
dengdenghui 发表于 2018-8-10 15:35
可以问一下啥编辑软件嘛这个配色很舒服

http://www.sublimetext.com/
xiajintaord 回答时间:2018-8-10 17:34:29
问题还未解决,在‘摸索中,’先记一下,解决了再来结贴总结吧。
xmstudio 回答时间:2018-8-10 20:02:10
你的设备没有CS这个引脚吗,SPI做一主多从还是很容易的

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

feixiang20 回答时间:2018-8-11 00:35:06
楼上大家也说了这么多了,那我给你提供一个参考。
#include<reg52.h>  
//---------------------------------------------------------  
#define uchar unsigned char   
#define SDA   P3_6  
#define SCL   P3_7  
//-----------------------------------------------------------------------  
void delay_100us();  
void delay_1s();  
void i2c_start();  
void i2c_stop();  
void get_ack();  
void i2c_send_byte(uchar mydata);  
void i2c_write_byte(uchar dev_addr_wr,uchar word_addr,uchar mydata);  
uchar i2c_read_byte(uchar dev_addr_wr,uchar dev_addr2_rd,uchar word_addr);  
//------------------------------------------------------------------------  
/*void main()
{
    uchar temp;
    while(1)
    {
        i2c_write_byte(0xa2,0x00,0x00);
        temp=i2c_read_byte(0xa2,0xa3,0x02);
        delay_1s();
        P1= temp;
    }
}*/  
//-----------------------------------------     //here are the functions   
void delay_100us()  
{  
    unsigned char i;  
    for(i=5;i>0;i--)  
        {;}  
}  
//-----------------------------------------  
void delay_1s()  
{  
    unsigned char i,j,k;  
    for(i=100;i>0;i--)  
        for(j=50;j>0;j--)  
            for(k=100;k>0;k--)  
                {;}  
}  
//------------------------------------------  
void i2c_start()  
{  
    SCL=0;  
    delay_100us();  
    SDA=1;                              //a falling edge of sda when scl is high   
    delay_100us();   
    SCL=1;        
    delay_100us();                                                                        
    SDA=0;        
    delay_100us();                                                                        
    SCL=0;                              //keep the SDA and SCL low;  
    delay_100us();                                                                     

}  
//---------------------------------------  
void i2c_stop()  
{  
    SCL=0;                             //a upper edge of sda when scl is high  
    delay_100us();  
    SDA=0;  
    delay_100us();  
    SCL=1;  
    delay_100us();  
    SDA=1;   
    delay_100us();  
    SDA=0;  
    delay_100us();  
    SCL=0;                            //keep the SDA and SCL low;  

}     
//---------------------------------------  
void get_ack()  
{  
    do  
    {  
        SCL=0;  
        delay_100us();  
        SDA=1;  
        delay_100us();  
        SCL=1;  
        delay_100us();  
    }  
    while(SDA);  
}  
//----------------------------------------  
void i2c_send_byte(uchar byte)  
{  

    uchar i;  
    for(i=0;i<8;i++)  
        {  
            SCL=0;  
            delay_100us();  
            SDA=byte&0x80;  
            delay_100us();  
            SCL=1;   
            delay_100us();  
            SCL=0;  
            delay_100us();  
            byte=byte<<1;  
        }  
    get_ack();        
}  
//----------------------------------------  
void i2c_write_byte(uchar dev_addr_wr,uchar word_addr,uchar mydata)  
{  
    i2c_start();  
    i2c_send_byte(dev_addr_wr);  
    i2c_send_byte(word_addr);  
    i2c_send_byte(mydata);  
    i2c_stop();  
}  
//----------------------------------------  
uchar  i2c_read_byte(uchar dev_addr_wr,uchar dev_addr_rd,uchar word_addr)  
{  
     uchar temp,i;  
     temp=0xff;  
     //---------------  
     i2c_start();  
     i2c_send_byte(dev_addr_wr);  
     i2c_send_byte(word_addr);  
     i2c_stop();                        //inital the address of device and word  
     //-------------------------------------------------------------------------  
     i2c_start();  
     i2c_send_byte(dev_addr_rd);  
     for(i=0;i<8;i++)  
        {  
            SCL=0;  
            delay_100us();  
            SDA=1;  
            delay_100us();  
            SCL=1;  
            delay_100us();  
            if(SDA)  
                {  
                    temp|=0x01;  
                }  
            else  
                {  
                    temp&=0xfe;  
                }  
             delay_100us();  
             SCL=0;  
             delay_100us();  
             temp=temp<<1;  
        }      
    SCL=0;  
    SDA=1;  
    SCL=1;  
    SCL=0;                      //read data from device  
     //-----------------------------------------------------------------------   
    i2c_stop();                 //stop the device  
    return temp;  

}  

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

dengdenghui 回答时间:2018-8-13 10:01:39
xiajintaord 发表于 2018-8-10 17:25
http://www.sublimetext.com/

嗯谢谢你 这个配色对眼睛好
xiajintaord 回答时间:2018-8-14 15:16:32
结贴:
00 01工作模式的模拟 SPI 已经调试完成了,都在下面的附件里面;
大家基本上用的都是硬件的 SPI,但有时候受限于成本,硬件资源不足的情况下,像 IIC 一样软件模拟的 SPI 也是一个不错的选择啊。
仅仅是修改部分代码,主要是针对 SCLK 时序,要理解 SPI 在不同的工作模式下的数据收发时序;
simulate_spi.rar (895 Bytes, 下载次数: 14)
xiajintaord 回答时间:2018-8-14 15:21:15
网络问题,导致重复提交了。。。
12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版