OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
楼主: suqingxiao

STM32 SPI双机通信(主从全双工),绝对原创,申请酷帖

  [复制链接]

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2014-10-27 12:27:24 | 显示全部楼层
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
正点原子逻辑分析仪DL16劲爆上市
回复 支持 反对

使用道具 举报

14

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-11-19
在线时间
3 小时
发表于 2014-10-31 23:02:43 | 显示全部楼层
回复【4楼】suqingxiao:
---------------------------------
你的程序好像没用,求指导
回复 支持 反对

使用道具 举报

14

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-11-19
在线时间
3 小时
发表于 2014-10-31 23:03:46 | 显示全部楼层
回复【4楼】suqingxiao:
---------------------------------
从机进不了中断
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2013-8-18
在线时间
6 小时
发表于 2014-11-8 09:46:58 | 显示全部楼层
按照中文手册来弄,主机传数据给从机之前,从机的输出缓存得有数据,可以在从机初始化的时候,先往从机的输出缓存存入一个值,然后在接受中断的地方,每当接受到一个数据,就往从机的缓存存入数据,这样就应该可以循环了
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-12-5
在线时间
0 小时
发表于 2014-12-5 14:29:41 | 显示全部楼层
测试楼主的代码,时发现: 
我在从机上回复TxBuf = {0x01, 0x02, 0x03, 0x04}; 但是主机收到的数据却是0x04, 0x01, 0x02, 0x03不知道为什么?
希望大神们解答
回复 支持 反对

使用道具 举报

1

主题

215

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
254
金钱
254
注册时间
2013-9-23
在线时间
4 小时
发表于 2014-12-12 17:01:03 | 显示全部楼层
很好,mark!马上要搞外部ic与stm32spi通信,应该会借鉴到。
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2015-1-8
在线时间
0 小时
发表于 2015-1-8 20:34:22 | 显示全部楼层
感谢一楼原创!按您的程序调试通过了。做了点小修改,如下,在我这测试通过了,欢迎大家测试:
1.发送端可以不用使能中断
2.主从机的spi的时钟可以设置到9MHz(更高的没有试验)
2.接收端:改成每次接收spi1_rec_buf_MAX
void SPI1_IRQHandler(void)
{
if((SPI1->SR&1<<0)==1) 
{
spi1_rec_buf[rec_cnt++] = SPI1_ReadByte(0x00);
//SPI1_ReadWriteByte(0xaa);//如果不注释掉会丢掉1半的数
if(rec_cnt>=spi1_rec_buf_MAX)
{
  spi1_rec_flag=1;
  rec_cnt=0;
}
}
}
回复 支持 1 反对 0

使用道具 举报

15

主题

143

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
243
金钱
243
注册时间
2014-10-31
在线时间
4 小时
发表于 2015-1-20 10:08:13 | 显示全部楼层
顶顶顶!!果断收藏
总有一天,要为自由而活
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2013-7-16
在线时间
71 小时
发表于 2015-1-20 10:33:55 | 显示全部楼层
楼主能否做个双机的SPI--DMA收发啊?
回复 支持 反对

使用道具 举报

23

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
306
金钱
306
注册时间
2014-9-24
在线时间
39 小时
发表于 2015-1-25 15:30:07 | 显示全部楼层
好东西,正好要用
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2015-4-15
在线时间
3 小时
发表于 2015-4-15 14:03:15 | 显示全部楼层
回复【55楼】Foveove:
---------------------------
 出现54楼现象的原因是:在每次进入从机接收中断前,没有给发送缓冲器写入数据。
 所以,在进入下次从机接收中断前,要先给发送缓冲器写入数据,
即调用函数:u8 SPI1_ReadWriteByte(u8 TxData)例如SPI1_ReadWriteByte(0x17);
 可以参考论坛帖子:http://www.openedv.com/posts/list/42853.htm#246182中的4楼。

回复 支持 反对

使用道具 举报

38

主题

302

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
440
金钱
440
注册时间
2012-3-6
在线时间
5 小时
发表于 2015-4-15 14:27:38 | 显示全部楼层
虽然没用到。六个爪印以后要用来看。
ES?全称?Embedded?Show;ES是由众多嵌入式爱好者组织的一个团队,致力于带领学生进步,帮助毕业生找到工作,更重要的是在职的嵌入式工作者提供自主外包和创业的机会。(详情进群查看) ES的宗旨是:交流共享与合作发展。ES?QQ群?第三群:152820643?。群内论坛有很多嵌入式开发模块解决方案可以参考。进群的立马共享自己做的模块简介。
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
28
金钱
28
注册时间
2015-1-26
在线时间
0 小时
发表于 2015-5-23 11:12:44 | 显示全部楼层
回复【46楼】andy93762:
------------------------------请问你的问题解决了没?怎么解决的呢?
回复 支持 反对

使用道具 举报

7

主题

32

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2015-4-16
在线时间
13 小时
发表于 2015-6-2 10:51:16 | 显示全部楼层
回复【61楼】Godsboy:
---------------------------------
您好啊,我之前也出现了这样的问题;主机发送一个数组【0x26,0x22,0x23,0x45】 然后接收到的数据却是【0x26,0,0,0x23】这是什么原因呢?
  也是用的楼主的程序,求解啊~~~@_@
回复 支持 反对

使用道具 举报

7

主题

32

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2015-4-16
在线时间
13 小时
发表于 2015-6-2 10:56:30 | 显示全部楼层
回复【61楼】Godsboy:
---------------------------------
从机接收中断函数,将接收的数据放入数组RXbuffer【】,主机发送的数据是对的,但是从机接收的出现错误数据,个别数据是对的但是移位了;
有大神解答吗????????????
void SPI1_IRQHandler(void)
{
    int i=0;
while((SPI1->SR&1<<0)==1) 
{
    RxBuffer[i++]=SPI1_ReadByte(0x00);


}
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-3-9
在线时间
1 小时
发表于 2015-6-10 10:53:58 | 显示全部楼层
 Master_Temp = SPI1_ReadByte(0x00);这边的(0x00)表示什么  小弟刚学不太明白  而且我们我一次只能收发一个字节发不来8个字节  楼主求教  有没有发送数组的代码让我参考下 谢谢
学无止境
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2015-3-9
在线时间
1 小时
发表于 2015-6-10 17:27:35 | 显示全部楼层
想请教一下  我用楼主的程序来发8个字节给从机  不过通过串口在电脑显示出来时却发了12个字节出来 也就是最后一个字节发了5次


发送程序是这样的
[mw_shl_code=c,true] while(1) { SPI1_ReadWriteByte(0x01); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x02); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x03); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x04); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x05); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x06); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x07); //数据发送 delay_ms(300); SPI1_ReadWriteByte(0x08); //数据发送 delay_ms(300); // SPI1_ReadWriteByte(0x78); //数据发送 printf("Master_Temp =%x\r\n",Master_Temp); }[/mw_shl_code]
接收程序是这样的
[mw_shl_code=c,true]void SPI1_IRQHandler(void) { // u8 i; if((SPI1->SR&1<<0)==1) { Slave_Temp = SPI1_ReadByte(0xff); //0xff在空闲时mois维持高电平,当然原本的0x00也是可以的 ff比较稳定 if(Slave_Temp==0x01){ LED0=0; delay_ms(200); LED0=1; delay_ms(200); }else if(Slave_Temp==0x02){ LED1=0; delay_ms(200); LED1=1; delay_ms(200); }else if(Slave_Temp==0x03){ LED2=0; delay_ms(200); LED2=1; delay_ms(200); }else if(Slave_Temp==0x04){ LED3=0; delay_ms(200); LED3=1; delay_ms(200); }else if(Slave_Temp==0x05){ LED1=0; LED0=0; delay_ms(200); LED1=1; LED0=1; delay_ms(200); }else if(Slave_Temp==0x06){ LED1=0; LED2=0; delay_ms(200); LED1=1; LED2=1; delay_ms(200); }else if(Slave_Temp==0x07){ LED2=0; LED3=0; delay_ms(200); LED2=1; LED3=1; delay_ms(200); } SPI1_ReadWriteByte(0xaa); } [/mw_shl_code]
其它的都没有动过,就是会接到12个字节出来,请问这会是什么问题拿而且j-link去仿真的时候仿真不了
学无止境
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2015-4-15
在线时间
3 小时
发表于 2015-6-15 16:35:35 | 显示全部楼层
回复【64楼】laoqier:
---------------------------------
主要是你给SPI发送缓冲器写入数据的时间出现了问题,
在主机未给从机(STM32)发送数据之前,要先给从机的发送缓存器写入数据,如下所示。
 时间    主机发送数据       从机发送缓存器数据
 N+0   --------------------0x26
 N+1   0x26--------------0x22
 N+2   0x22--------------0x23
 N+3   0x23--------------0x45
 N+4   0x45-------------------
回复 支持 反对

使用道具 举报

0

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
402
金钱
402
注册时间
2014-3-17
在线时间
106 小时
发表于 2015-7-7 17:52:07 | 显示全部楼层
回复【68楼】Godsboy:
---------------------------------
你向从机发送缓冲器写的数据是下一时刻主机将要发送的数据。
请问如果不确定主机发送什么数据,应该向从机发送缓冲器写入
什么数据。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2015-3-20
在线时间
0 小时
发表于 2015-8-20 15:49:29 | 显示全部楼层
感谢楼主,目前正在看SPI通信的内容,涉及到了全双工SPI,及时雨!
回复 支持 反对

使用道具 举报

12

主题

33

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
254
金钱
254
注册时间
2014-5-26
在线时间
44 小时
发表于 2015-9-21 15:31:12 | 显示全部楼层
这不是标准的SPI通信协议,虽然可以实现双机通信,但是没有使用到CSN片选引脚
回复 支持 反对

使用道具 举报

6

主题

56

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2014-12-11
在线时间
3 小时
发表于 2015-9-21 16:26:33 | 显示全部楼层
大家讨论的好激烈,屌屌的。。。
我会让你以我为荣
回复 支持 反对

使用道具 举报

6

主题

56

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2014-12-11
在线时间
3 小时
发表于 2015-9-25 16:56:36 | 显示全部楼层
回复【21楼】lansing1648:
--------------------------------
我估计楼主这个地方疏忽写错了
我会让你以我为荣
回复 支持 反对

使用道具 举报

6

主题

56

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2014-12-11
在线时间
3 小时
发表于 2015-9-25 16:58:05 | 显示全部楼层
while((SPI1->SR&1<<1)==0)//等待发送区空 
这句话的0应该改成1才是等待发送为空
我会让你以我为荣
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-5-12
在线时间
0 小时
发表于 2015-10-19 17:35:36 | 显示全部楼层

主机

#include "sys.h" //系统子函数
#include "usart.h"//串口子函数  
#include "delay.h" //延时子函数
 // SPI总线速度设置 
#define SPI_SPEED_2   0
#define SPI_SPEED_8   1
#define SPI_SPEED_16  2
#define SPI_SPEED_256 3

u8 Master_Temp =0;
void SPI1_Init(void);    //初始化SPI口
void SPI1_SetSpeed(u8 SpeedSet); //设置SPI速度   
u8 SPI1_ReadWriteByte(u8 TxData);//SPI总线读写一个字节

int main(void)
{
   Stm32_Clock_Init(3); //系统时钟设置
   delay_init(24);//延时函数初始化
   uart_init(24,9600); //串口初始化
   SPI1_Init(); //SPI1初始化
   SPI1_SetSpeed(SPI_SPEED_256);//SPI速度两分频
   while(1)
   { 
       SPI1_ReadWriteByte(0x55);
       SPI1_ReadWriteByte(0x66);
       printf("Master_Temp  =%x\r\n",Master_Temp );
      delay_ms(100); 
   }
}

//SPI口初始化
//这里针是对SPI1的初始化
void SPI1_Init(void)

         RCC->APB2ENR|=1<<0; //复用 
         RCC->APB2ENR|=1<<2;       //PORTA时钟使能   
        RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
     
     //这里只针对SPI口初始化
     GPIOA->CRL&=0X000FFFFF; 
     GPIOA->CRL|=0XBBB00000;//PA5.6.7复用      
     GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉

  
     SPI1->CR1|=0<<10;//全双工模式 
     SPI1->CR1|=1<<9; //软件nss管理
     SPI1->CR1|=1<<8; 

     SPI1->CR1|=1<<2; //SPI主机
     SPI1->CR1|=0<<11;//8bit数据格式 
     SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
     SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1  
     SPI1->CR1|=0<<3; //Fsck=Fcpu/256
     SPI1->CR1|=0<<7; //MSBfirst 
 
     SPI1->CR2|=1<<6;      //接收缓冲区非空中断使能
     MY_NVIC_Init(1,0,SPI1_IRQChannel,4);   
   
     SPI1->CR1|=1<<6; //SPI设备使能
   
}   
//SPI 速度设置函数
//SpeedSet:
//SPI_SPEED_2   2分频   (SPI 12M    --sys 24M)
//SPI_SPEED_8   8分频   (SPI 3M     --sys 24M)
//SPI_SPEED_16  16分频  (SPI 1.5M    --sys 24M)
//SPI_SPEED_256 256分频 (SPI  905.6K --sys 24M)
void SPI1_SetSpeed(u8 SpeedSet)
{
         SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
     if(SpeedSet==SPI_SPEED_2)//二分频
     {
          SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz 
     }else if(SpeedSet==SPI_SPEED_8)//八分频 
     {
          SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz 
     }else if(SpeedSet==SPI_SPEED_16)//十六分频
     {
          SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
     }

    else      //256分频
     {
          SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
     }
     SPI1->CR1|=1<<6; //SPI设备使能   

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{  
     u8 retry=0;     
     while((SPI1->SR&1<<1)==0)//等待发送区空 
     {
          retry++;
          if(retry>200)return 0;
     }     
     SPI1->DR=TxData;     //发送一个byte 
     retry=0;
     while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
     {
          retry++;
          if(retry>200)return 0;
     }             
     return SPI1->DR;          //返回收到的数据        
}

u8 SPI1_ReadByte(u8 TxData)
{  
     u8 retry=0;    

      while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
     {
          retry++;
          if(retry>200)return 0;
     }             
     return SPI1->DR;          //返回收到的数据        
}


void SPI1_IRQHandler(void)

     if((SPI1->SR&1<<0)==1) 
     {  
          Master_Temp = SPI1_ReadByte(0x00);
     }  
}

 

 

从机

#include "sys.h" //系统子函数
#include "usart.h"//串口子函数  
#include "delay.h" //延时子函数
 // SPI总线速度设置 
#define SPI_SPEED_2   0
#define SPI_SPEED_8   1
#define SPI_SPEED_16  2
#define SPI_SPEED_256 3

u8 Slave_Temp=0;

void SPI1_Init(void);    //初始化SPI口
void SPI1_SetSpeed(u8 SpeedSet); //设置SPI速度   
u8 SPI1_ReadWriteByte(u8 TxData);

int main(void)
{
     Stm32_Clock_Init(3); //系统时钟设置
     delay_init(24);//延时函数初始化
     uart_init(24,9600); //串口初始化
     SPI1_Init(); //SPI1初始化
     SPI1_SetSpeed(SPI_SPEED_256);//SPI速度两分频
     MY_NVIC_Init(0,0,SPI1_IRQChannel,4);   //设置抢占优先级为1,响应优先级为1,中断分组为4
     while(1)
     { 
            printf("Slave_Temp=%x\r\n",Slave_Temp);
              delay_ms(100); 
        }
}

//SPI口初始化
//这里针是对SPI1的初始化
void SPI1_Init(void)
{  
     RCC->APB2ENR|=1<<0; //复用 
     RCC->APB2ENR|=1<<2;       //PORTA时钟使能   
     RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
     
     //这里只针对SPI口初始化
     GPIOA->CRL&=0X000FFFFF; 
     GPIOA->CRL|=0XBBB00000;//PA5.6.7复用      
     GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉

  
     SPI1->CR1|=0<<10;//全双工模式 
     SPI1->CR1|=1<<9; //软件nss管理
     SPI1->CR1|=0<<8;//ssi为0 

     SPI1->CR1|=0<<2; //SPI从机
     SPI1->CR1|=0<<11;//8bit数据格式 
     SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
     SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1  
     SPI1->CR1|=0<<3; //Fsck=Fcpu/256
     SPI1->CR1|=0<<7; //MSBfirst 
 
     SPI1->CR2|=1<<6;      //接收缓冲区非空中断使能
     MY_NVIC_Init(1,0,SPI1_IRQChannel,4);    
  
     SPI1->CR1|=1<<6; //SPI设备使能  
}   
//SPI 速度设置函数
//SpeedSet:
//SPI_SPEED_2   2分频   (SPI 12M    --sys 24M)
//SPI_SPEED_8   8分频   (SPI 3M     --sys 24M)
//SPI_SPEED_16  16分频  (SPI 1.5M    --sys 24M)
//SPI_SPEED_256 256分频 (SPI  905.6K --sys 24M)
void SPI1_SetSpeed(u8 SpeedSet)
{
     SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
     if(SpeedSet==SPI_SPEED_2)//二分频
     {
          SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz 
     }
     else if(SpeedSet==SPI_SPEED_8)//八分频 
     {
          SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz 
     }
     else if(SpeedSet==SPI_SPEED_16)//十六分频
     {
          SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
     }
     else      //256分频
     {
          SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
     }
     SPI1->CR1|=1<<6; //SPI设备使能   
}


u8 SPI1_ReadWriteByte(u8 TxData)
{  
     u8 retry=0;     
     while((SPI1->SR&1<<1)==0)//等待发送区空 
     {
          retry++;
          if(retry>200)return 0;
     }     
     SPI1->DR=TxData;     //发送一个byte 
     retry=0;
     while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
     {
          retry++;
          if(retry>200)return 0;
     }             
     return SPI1->DR;          //返回收到的数据        
}

u8 SPI1_ReadByte(u8 TxData)
{  
     u8 retry=0;     
 //   while((SPI1->SR&1<<1)==0)//等待发送区空 
  //   {
   //       retry++;
   //       if(retry>200)return 0;
  //   }     
   //  SPI1->DR=TxData;     //发送一个byte 
   //  retry=0;
     while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
     {
          retry++;
          if(retry>200)return 0;
     }             
     return SPI1->DR;          //返回收到的数据        
}


void SPI1_IRQHandler(void)
{
      if((SPI1->SR&1<<0)==1) 
     {     
          Slave_Temp = SPI1_ReadByte(0x00); 
          SPI1_ReadWriteByte(0xaa); 
     }  
}


改进:把主机改成查询接收也是可以的,这时只要一个发送,是真正意义上的全双工了。

主机:

#include "sys.h" //系统子函数
#include "usart.h"//串口子函数  
#include "delay.h" //延时子函数
#include "TIMER.h"

 // SPI总线速度设置 
#define SPI_SPEED_2   0
#define SPI_SPEED_8   1
#define SPI_SPEED_16  2
#define SPI_SPEED_256 3

u8 Master_Temp =0;
void SPI1_Init(void);    //初始化SPI口
void SPI1_SetSpeed(u8 SpeedSet); //设置SPI速度   
void SPI1_WriteByte(u8 TxData);//SPI总线读写一个字节
u8 SPI1_ReadByte(u8 TxData);

int main(void)
{
 Stm32_Clock_Init(3); //系统时钟设置
 delay_init(24);//延时函数初始化
 uart_init(24,9600); //串口初始化
 SPI1_Init(); //SPI1初始化
 SPI1_SetSpeed(SPI_SPEED_256);//SPI速度两分频
 

 while(1)
 { 
     SPI1_WriteByte(0x55); 
  Master_Temp = SPI1_ReadByte(0x00);
  printf("Master_Temp =%x\r\n",Master_Temp);
  delay_ms(100); 
 }
}

//SPI口初始化
//这里针是对SPI1的初始化
void SPI1_Init(void)

 RCC->APB2ENR|=1<<0; //复用 
 RCC->APB2ENR|=1<<2;       //PORTA时钟使能   
 RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
     
 //这里只针对SPI口初始化
 GPIOA->CRL&=0X000FFFFF; 
 GPIOA->CRL|=0XBBB00000;//PA5.6.7复用      
 GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉

  
 SPI1->CR1|=0<<10;//全双工模式 
 SPI1->CR1|=1<<9; //软件nss管理
 SPI1->CR1|=1<<8; 

 SPI1->CR1|=1<<2; //SPI主机
 SPI1->CR1|=0<<11;//8bit数据格式 
 SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
 SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1  
 SPI1->CR1|=0<<3; //Fsck=Fcpu/256
 SPI1->CR1|=0<<7; //MSBfirst 
 
 //SPI1->CR2|=1<<6;      //接收缓冲区非空中断使能
 //MY_NVIC_Init(8,0,SPI1_IRQChannel,4);   
   
 SPI1->CR1|=1<<6; //SPI设备使能
   
}   
//SPI 速度设置函数

void SPI1_SetSpeed(u8 SpeedSet)
{
 SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
 if(SpeedSet==SPI_SPEED_2)//二分频
 {
  SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz 
 }else if(SpeedSet==SPI_SPEED_8)//八分频 
 {
  SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz 
 }else if(SpeedSet==SPI_SPEED_16)//十六分频
 {
  SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
 }else      //256分频
 {
  SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
 }
 SPI1->CR1|=1<<6; //SPI设备使能   

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
void SPI1_WriteByte(u8 TxData)
{  
 u8 retry=0;     
 while((SPI1->SR&1<<1)==0)//等待发送区空 
 {
  retry++;
  if(retry>200)return;
 }     
 SPI1->DR=TxData;     //发送一个byte        
}

u8 SPI1_ReadByte(u8 TxData)
{  
 u8 retry=0;    

 while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
 {
  retry++;
  if(retry>200)return 0;
 }             
 return SPI1->DR;          //返回收到的数据        
}

我想知道 硬件  怎么接啊  求指导

回复 支持 反对

使用道具 举报

11

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2014-11-9
在线时间
5 小时
发表于 2015-10-21 11:12:58 | 显示全部楼层
不知为啥,我的SPI双机通讯配置和大家一样,但是就是死活通讯不了
加油,奋斗
回复 支持 反对

使用道具 举报

74

主题

334

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
436
金钱
436
注册时间
2015-5-28
在线时间
144 小时
发表于 2015-10-26 15:18:58 | 显示全部楼层
mark一下
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2015-11-13
在线时间
0 小时
发表于 2015-11-13 16:28:10 | 显示全部楼层
 学习一下
回复 支持 反对

使用道具 举报

4

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-8-18
在线时间
11 小时
发表于 2015-11-16 17:52:32 | 显示全部楼层
mark 好东西
回复 支持 反对

使用道具 举报

13

主题

296

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2066
金钱
2066
注册时间
2012-5-26
在线时间
291 小时
发表于 2015-12-1 16:49:00 | 显示全部楼层
谢谢分享, 最近要用到
活着才是王道!健康是一切的前提!
回复 支持 反对

使用道具 举报

4

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2015-12-4
在线时间
17 小时
发表于 2015-12-4 10:50:52 | 显示全部楼层
学习了,改成SPI3要怎么做呢?
回复 支持 反对

使用道具 举报

12

主题

126

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2013-1-5
在线时间
22 小时
发表于 2015-12-20 15:44:10 | 显示全部楼层
学习了,多谢楼主分享
天道酬勤
回复 支持 反对

使用道具 举报

12

主题

126

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2013-1-5
在线时间
22 小时
发表于 2015-12-23 12:57:05 | 显示全部楼层
回复【69楼】行者person:
---------------------------------
它这个是测试循环收发的,真正用的时候不会这么干,从机只需要填写自己要返回的数据即可
天道酬勤
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2015-11-19
在线时间
3 小时
发表于 2016-1-11 17:06:08 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

69

主题

978

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3772
金钱
3772
注册时间
2015-4-26
在线时间
765 小时
发表于 2016-1-11 17:30:38 | 显示全部楼层
感谢分享,非常不错
我有故事,你有酒吗
回复 支持 反对

使用道具 举报

3

主题

92

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2012-6-19
在线时间
37 小时
发表于 2016-2-16 13:54:18 | 显示全部楼层
非常感谢,楼主的精神值得学习。
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2013-6-15
在线时间
32 小时
发表于 2016-2-23 08:51:00 | 显示全部楼层
顶一下
回复 支持 反对

使用道具 举报

8

主题

97

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
17563
金钱
17563
注册时间
2016-1-20
在线时间
63 小时
发表于 2016-2-23 09:18:49 | 显示全部楼层
下载 研究研究 双吉通讯很有用
---------------------------------------------------
个人论坛博客:macian.cn
个人淘宝小店:macian.taobao.com
回复 支持 反对

使用道具 举报

6

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
71
金钱
71
注册时间
2015-7-20
在线时间
12 小时
发表于 2016-3-2 08:11:08 | 显示全部楼层
simms01 发表于 2013-7-22 15:15
正在研究这个问题 果然是想睡觉马上有人送枕头 感觉太好了

谢谢老哥的枕头。非常感激

最近也在学一主机多从机的问题,你的弄得怎么样了?求资料!
回复 支持 反对

使用道具 举报

4

主题

11

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2016-2-16
在线时间
5 小时
发表于 2016-3-20 12:59:20 | 显示全部楼层
SPI1_SetSpeed(SPI_SPEED_256);//SPI速度两分频

从机也需要设定时钟吗
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-3-24
在线时间
1 小时
发表于 2016-3-24 09:09:27 | 显示全部楼层
mark留着备用
回复 支持 反对

使用道具 举报

5

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
329
金钱
329
注册时间
2015-9-11
在线时间
46 小时
发表于 2016-3-28 09:22:03 | 显示全部楼层
有库函数版本吗?
迫于生计
回复 支持 反对

使用道具 举报

4

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-3-16
在线时间
7 小时
发表于 2016-3-29 11:06:07 | 显示全部楼层
之前做过spi双机通信的,只是都是MASTER发起,没有试过SLAVE要给MASTER发数据时是怎么发起的呢?
1、主从切换?但是切换的时机不好掌握,这个问题在主机和从机都想往对方送信的情况下尤其明显,比较方便的方法是主机定周期发送数据(也可以是空数据包),同时收取从机数据包,一般情况下都可以满足通信要求。
2、从机有发送要求时给主机一个信号,一般用一个端子电平变化,主机利用外部中断截获这个信号,然后驱动通信?
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2016-4-5
在线时间
1 小时
发表于 2016-4-5 19:19:15 | 显示全部楼层
好强大
回复 支持 反对

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2013-3-26
在线时间
11 小时
发表于 2016-4-7 13:48:49 | 显示全部楼层
顶。。。。。。。。以后会用到
回复 支持 反对

使用道具 举报

4

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
193
金钱
193
注册时间
2016-1-14
在线时间
42 小时
发表于 2016-4-7 13:55:07 | 显示全部楼层
真强大 自己默默的来顶一下
回复 支持 反对

使用道具 举报

鱼塘yu 该用户已被删除
发表于 2016-4-23 16:54:59 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

1

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
232
金钱
232
注册时间
2016-8-9
在线时间
29 小时
发表于 2016-8-9 14:00:07 | 显示全部楼层
不知道楼主有没有试过STM32F107 的SPI3 ,SPI3的MOSI上一直是0XFF
回复 支持 反对

使用道具 举报

1

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
232
金钱
232
注册时间
2016-8-9
在线时间
29 小时
发表于 2016-8-9 14:02:11 | 显示全部楼层
这个ST官方有代码的。将一个STm32的SPi1和SPi2连接
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : main.c
* Author             : MCD Application Team
* Version            : V1.0
* Date               : 10/08/2007
* Description        : Main program body
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"

/* Local includes ------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

/* Private define ------------------------------------------------------------*/
#define BufferSize 32

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
SPI_InitTypeDef   SPI_InitStructure;
u8 SPI1_Buffer_Tx[BufferSize] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
                                 0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,
                                 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
                                 0x1C,0x1D,0x1E,0x1F,0x20};
u8 SPI2_Buffer_Tx[BufferSize] = {0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
                                 0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,
                                 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,
                                 0x6C,0x6D,0x6E,0x6F,0x70};
u8 SPI1_Buffer_Rx[BufferSize], SPI2_Buffer_Rx[BufferSize];
u8 Tx_Idx = 0, Rx_Idx = 0, k = 0;
volatile TestStatus TransferStatus1 = FAILED, TransferStatus2 = FAILED;
volatile TestStatus TransferStatus3 = FAILED, TransferStatus4 = FAILED;
ErrorStatus HSEStartUpStatus;

/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
TestStatus Buffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength);

/*******************************************************************************
* Function Name  : main
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
  debug();
#endif

  /* System clocks configuration ---------------------------------------------*/
  RCC_Configuration();

  /* NVIC configuration ------------------------------------------------------*/
  NVIC_Configuration();

  /* GPIO configuration ------------------------------------------------------*/
  GPIO_Configuration();

  /* 1st phase: SPI1 Master and SPI2 Slave */
  /* SPI1 Config -------------------------------------------------------------*/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  /* SPI2 Config -------------------------------------------------------------*/
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_Init(SPI2, &SPI_InitStructure);

  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);
  /* Enable SPI2 */
  SPI_Cmd(SPI2, ENABLE);

  /* Transfer procedure */
  while(Tx_Idx<BufferSize)
  {
    /* Wait for SPI1 Tx buffer empty */
    while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE)==RESET);
    /* Send SPI2 data */
    SPI_SendData(SPI2, SPI2_Buffer_Tx[Tx_Idx]);       
    /* Send SPI1 data */
    SPI_SendData(SPI1, SPI1_Buffer_Tx[Tx_Idx++]);     
    /* Wait for SPI2 data reception */
    while(SPI_GetFlagStatus(SPI2, SPI_FLAG_RXNE)==RESET);
    /* Read SPI2 received data */
    SPI2_Buffer_Rx[Rx_Idx] = SPI_ReceiveData(SPI2);
    /* Wait for SPI1 data reception */
    while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE)==RESET);
    /* Read SPI1 received data */
    SPI1_Buffer_Rx[Rx_Idx++] = SPI_ReceiveData(SPI1);                 
  }

  /* Check the corectness of written dada */
  TransferStatus1 = Buffercmp(SPI2_Buffer_Rx, SPI1_Buffer_Tx, BufferSize);
  TransferStatus2 = Buffercmp(SPI1_Buffer_Rx, SPI2_Buffer_Tx, BufferSize);
  /* TransferStatus1, TransferStatus2 = PASSED, if the transmitted and received data
     are equal */
  /* TransferStatus1, TransferStatus2 = FAILED, if the transmitted and received data
     are different */

  /* 2nd phase: SPI1 Slave and SPI2 Master */  
  /* SPI1 Re-configuration ---------------------------------------------------*/
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_Init(SPI1, &SPI_InitStructure);

  /* SPI2 Re-configuration ---------------------------------------------------*/
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_Init(SPI2, &SPI_InitStructure);

  /* Reset Tx_Idx, Rx_Idx indexes and receive tables values */
  Tx_Idx=0;
  Rx_Idx=0;
  for(k=0; k<BufferSize; k++)  SPI2_Buffer_Rx[k]=0;
  for(k=0; k<BufferSize; k++)  SPI1_Buffer_Rx[k]=0;

  /* Transfer procedure */
  while(Tx_Idx<BufferSize)
  {
    /* Wait for SPI2 Tx buffer empty */
    while(SPI_GetFlagStatus(SPI2, SPI_FLAG_TXE)==RESET);
    /* Send SPI1 data */
    SPI_SendData(SPI1, SPI1_Buffer_Tx[Tx_Idx]);
    /* Send SPI2 data */
    SPI_SendData(SPI2, SPI2_Buffer_Tx[Tx_Idx++]);
    /* Wait for SPI1 data reception */
    while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE)==RESET);
    /* Read SPI1 received data */
    SPI1_Buffer_Rx[Rx_Idx] = SPI_ReceiveData(SPI1);
    /* Wait for SPI2 data reception */
    while(SPI_GetFlagStatus(SPI2, SPI_FLAG_RXNE)==RESET);
    /* Read SPI2 received data */
    SPI2_Buffer_Rx[Rx_Idx++] = SPI_ReceiveData(SPI2);
  }

  /* Check the corectness of written dada */
  TransferStatus3 = Buffercmp(SPI2_Buffer_Rx, SPI1_Buffer_Tx, BufferSize);
  TransferStatus4 = Buffercmp(SPI1_Buffer_Rx, SPI2_Buffer_Tx, BufferSize);
  /* TransferStatus3, TransferStatus4 = PASSED, if the transmitted and received data
     are equal */
  /* TransferStatus3, TransferStatus4 = FAILED, if the transmitted and received data
     are different */

  while (1)
  {
  }
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
  
    /* PCLK2 = HCLK/2 */
    RCC_PCLK2Config(RCC_HCLK_Div2);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }

/* Enable peripheral clocks --------------------------------------------------*/
  /* GPIOA, GPIOB and SPI1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_SPI1, ENABLE);
  /* SPI2 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure SPI1 pins: SCK, MISO and MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure SPI2 pins: SCK, MISO and MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures NVIC and Vector Table base location.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif
}

/*******************************************************************************
* Function Name  : Buffercmp
* Description    : Compares two buffers.
* Input          : - pBuffer1, pBuffer2: buffers to be compared.
*                : - BufferLength: buffer's length
* Output         : None
* Return         : PASSED: pBuffer1 identical to pBuffer2
*                  FAILED: pBuffer1 differs from pBuffer2
*******************************************************************************/
TestStatus Buffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength)
{
  while(BufferLength--)
  {
    if(*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }
   
    pBuffer1++;
    pBuffer2++;
  }

  return PASSED;  
}

#ifdef  DEBUG
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert_param error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert_param error line source number
* Output         : None
* Return         : None
*******************************************************************************/
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/
回复 支持 1 反对 0

使用道具 举报

3

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2016-8-16
在线时间
13 小时
发表于 2016-8-17 10:49:14 | 显示全部楼层
DDDDMARK
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-11 07:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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