打印

单片机IO口模拟SPI四种模式的程序

[复制链接]
1643|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

沙发
王大熊|  楼主 | 2015-5-27 09:06 | 只看该作者

使用特权

评论回复
板凳
王大熊|  楼主 | 2015-5-27 09:06 | 只看该作者
本帖最后由 王大熊 于 2015-5-27 09:09 编辑
#include "iom8535v.h"
#define _CPOL     1
#define _CPHA     0
#define SCK_IO    DDRA|=0X01
#define MOSI_IO   DDRA|=0X02
#define MISO_IO   DDRA&=0XFB
#define SSEL_IO   DDRA|=0X08
#define SCK_D(X)   (X?(PORTA|=0X01):(PORTA&=0XFE))
#define MOSI_D(X)  (X?(PORTA|=0X02):(PORTA&=0XFD))
#define SSEL_D(X)  (X?(PORTA|=0X08):(PORTA&=0XF7))

#define MISO_I()  (PINA&0X04)  
void delay()
{
unsigned char m,n;
     for(n=0;n<5;n++);
    for(m=0;m<100;m++);
}
/************************************************
        端口方向配置  与输出初始化
************************************************/
void SPI_Init(void)
{
SCK_IO   ;
MOSI_IO  ;
MISO_IO  ;
SSEL_IO  ;
SSEL_D(1);
MOSI_D(1);
#if _CPOL==0
SCK_D(0);
#else
SCK_D(1);
#endif
}

/**********************************************
模式零           写数据
***********************************************/
#if _CPOL==0&&_CPHA==0          //MODE   0  0   
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
for(n=0;n<8;n++)
{
  SCK_D(0);
  if(dat&0x80)MOSI_D(1);
  else MOSI_D(0);
  dat<<=1;
  SCK_D(1);
}
  SCK_D(0);
}
/*********************************************
模式零         读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
  SCK_D(0);
  dat<<=1;
  if(MISO_I())dat|=0x01;
  else dat&=0xfe;
  SCK_D(1);
}
  SCK_D(0);
  return dat;
}
#endif
/**********************************************
模式二           写数据
***********************************************/
#if _CPOL==1&&_CPHA==0           //MODE   1  0
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
for(n=0;n<8;n++)
{
  SCK_D(1);
  if(dat&0x80)MOSI_D(1);
  else MOSI_D(0);
  dat<<=1;
  SCK_D(0);
}
  SCK_D(1);
}
/*********************************************
模式二          读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
  SCK_D(1);
  dat<<=1;
  if(MISO_I())dat|=0x01;
  else dat&=0xfe;
  SCK_D(0);
}
  SCK_D(1);
  return dat;
}

#endif
/*********************************************
模式一        写数据
*********************************************/
#if _CPOL==0&&_CPHA==1           //MODE  0  1
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
SCK_D(0);
for(n=0;n<8;n++)
{
  SCK_D(1);
  if(dat&0x80)MOSI_D(1);
  else MOSI_D(0);
  dat<<=1;
  SCK_D(0);
}
}
/*********************************************
模式一       读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
  SCK_D(1);
   dat<<=1;
  if(MISO_I())dat|=0x01;
  else dat&=0xfe;
  SCK_D(0);
}
  SCK_D(0);
  return dat;
}
#endif
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////

#if _CPOL==1&&_CPHA==1            //MODE  1  1
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
SCK_D(1);
for(n=0;n<8;n++)
{
  SCK_D(0);
  if(dat&0x80)MOSI_D(1);
  else MOSI_D(0);
  dat<<=1;
  SCK_D(1);
}
}
/************************************
模式三          读数据
************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
SCK_D(0);
for(n=0;n<8;n++)
{ SCK_D(0);
  dat<<=1;
  if(MISO_I())dat|=0x01;
  else dat&=0xfe;
  SCK_D(1);
}
  SCK_D(1);
  return dat;
}
#endif
/*************************************
*************************************/
void main()
{

SPI_Init();
DDRB = 0XFF;
//#if _CPOL
//SCK_D(0);
//#endif
while(1)
{
//SSEL_D(0);
//SPI_Send_Dat(0x01);
//SPI_Send_Dat(0x31);
//SSEL_D(1);
SSEL_D(0);
SPI_Send_Dat(0x81);
PORTB =SPI_Receiver_Dat();
SSEL_D(1);
//delay();
}
}

使用特权

评论回复
地板
vivilzb1985| | 2015-6-8 19:49 | 只看该作者

这个主要需要注意这个时序的顺序的。

使用特权

评论回复
5
shenmu2012| | 2015-6-10 19:36 | 只看该作者
信号的起始位跟结束位的需要注意的。

使用特权

评论回复
6
firstblood| | 2015-6-11 19:13 | 只看该作者

时序是很重要的,注意起始位的。

使用特权

评论回复
7
angerbird| | 2015-6-15 21:09 | 只看该作者
这个需要注意单片机的主频频率大小的,主频太小的话肯定是不行的。

使用特权

评论回复
8
smilingangel| | 2015-6-16 20:35 | 只看该作者

这个程序中怎不需要加短延时程序的?

使用特权

评论回复
9
王大熊|  楼主 | 2015-6-22 09:40 | 只看该作者
smilingangel 发表于 2015-6-16 20:35
这个程序中怎不需要加短延时程序的?

一般都不用加的,实际测试没什么问题。

使用特权

评论回复
10
comeon201208| | 2015-7-11 17:35 | 只看该作者
这个是需要注意信号的时序的,特别是首尾信号的电平变化的。

使用特权

评论回复
11
firstblood| | 2015-7-15 21:34 | 只看该作者

注意这个时序信号的操作很重要的。

使用特权

评论回复
12
make8419247| | 2015-7-16 12:07 | 只看该作者
4种模式全部测试通过了吗

使用特权

评论回复
13
王大熊|  楼主 | 2015-7-17 09:15 | 只看该作者
make8419247 发表于 2015-7-16 12:07
4种模式全部测试通过了吗

都是可以的。

使用特权

评论回复
14
make8419247| | 2015-7-17 15:14 | 只看该作者
两个GD32之间的SPI是不是主机和分机的模式都必须一致

使用特权

评论回复
15
angerbird| | 2015-7-17 22:18 | 只看该作者
没看懂上边的时序图中的CPOL的信号是干啥的

使用特权

评论回复
16
zhangbo1985| | 2015-7-26 23:03 | 只看该作者
四种模式?总么讲啊。。。一般就是数据的读写的呗。

使用特权

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

本版积分规则

22

主题

236

帖子

0

粉丝