8位单片机 普通IO模拟SPIMaster 之前写的模拟SPI 怕丢了,直接粘贴过来,平台是南京沁恒CH559 8位单片机


/********************************** (C) COPYRIGHT *******************************
* File Name          : SPI0Mater.C
* Author             : WCH
* Version            : V1.3
* Date               : 2016/06/24
* Description        : CH559提供SPI0主机模式操作接口函数             				   
*******************************************************************************/
#include "..\DEBUG.C"                                                          //调试信息打印
#include "..\DEBUG.H"

#define SPI0Interrupt   0                                                      //设定SPI0数据收发中断方式或者查询方式
UINT8 flag;
UINT8 TmpBuf;

#pragma  NOAREGS
#define SET_SPI0_CK( d )   { SPI0_CK_SE = d; }                                 //d>=2

/*硬件接口定义*/
/******************************************************************************
使用CH559 硬件SPI接口 
         CH559        DIR       
         P1.4        <==>       SCS
         P1.5        <==>       MOSI
         P1.6        <==>       MISO
         P1.7        <==>       SCK
*******************************************************************************/

/*******************************************************************************
* Function Name  : CH559SPI0InterruptInit()
* Description    : CH559SPI0中断初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH559SPI0InterruptInit()
{
    //IP_EX |= bIP_SPI0;                                                       //SPI0中断优先级设置
    SPI0_SETUP |= bS0_IE_FIFO_OV | bS0_IE_BYTE;                                //使能接收1字节中断,使能FIFO溢出中断
    SPI0_CTRL |= bS0_AUTO_IF;                                                  //自动清S0_IF_BYTE中断标志
    SPI0_STAT |= 0xff;                                                         //清空SPI0中断标志
#if SPI0Interrupt
    IE_SPI0 = 1;                                                               //使能SPI0中断
#endif
}


/*******************************************************************************
* Function Name  : CH559SPI0HostInit()
* Description    : CH559SPI0初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH559SPI0HostInit(void)
{
    PORT_CFG &= ~bP1_OC;
    P1_DIR |= (bSCK | bMOSI | bSCS);
    P1_IE |= bMISO;                                                            //引脚配置
	
    SPI0_SETUP &= ~(bS0_MODE_SLV | bS0_BIT_ORDER);                             //设置为主机模式,字节顺序为大端模式		
    SPI0_CTRL |=  bS0_MOSI_OE  | bS0_SCK_OE ;                                  //MISO输出使能,SCK输出使能
    SPI0_CTRL &= ~(bS0_MST_CLK | bS0_2_WIRE);
    SPI0_CTRL &=  ~(bS0_DATA_DIR);                                             //主机写,默认不启动写传输,如果使能bS0_DATA_DIR,
	                                                                             //那么发送数据后自动产生一个字节的时钟,用于快速数据收发	
    SPI0_CK_SE = 0x40;
    SPI0_CTRL &= ~bS0_CLR_ALL;                                                 //清空SPI0的FIFO,默认是1,必须置零才能发送数据
}

/*******************************************************************************
* Function Name  : CH559SPI0Write(UINT8 dat)
* Description    : CH559硬件SPI写数据
* Input          : UINT8 dat   数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH559SPI0Write(UINT8 dat)
{
    SPI0_DATA = dat;                                                           
    while(S0_FREE == 0);													   //等待传输完成		
//如果bS0_DATA_DIR为1,此处可以直接读取一个字节的数据用于快速读写	
}

/*******************************************************************************
* Function Name  : CH559SPI0Read( )
* Description    : CH559硬件SPI0读数据
* Input          : None
* Output         : None
* Return         : UINT8 ret   
*******************************************************************************/
UINT8 CH559SPI0Read()
{
    SPI0_DATA = 0xff;
    while(S0_FREE == 0);
    return SPI0_DATA;
}

#if SPI0Interrupt
/*******************************************************************************
* Function Name  : SPI0HostInterrupt(void)
* Description    : SPI0 主机模式中断服务程序
* Input          : None
* Output         : None
* Return         : UINT8 ret   
*******************************************************************************/
void	SPI0HostInterrupt( void ) interrupt INT_NO_SPI0 using 1                //SPI0中断服务程序,使用寄存器组1
{ 
    if(flag == 0)
    {
        while(S0_FREE == 0);
    }
    if(flag == 1)
    {
        while(S0_FREE == 0);
        TmpBuf = SPI0_DATA;
    }
    //printf("sta %02X",(UINT16)SPI0_STAT);
    //printf("fl %02X",(UINT16)flag);
    SPI0_STAT = 0xff; 
}
#endif
///模拟spi进行通讯
#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();
}
}
void main()
{
    UINT8 ret,i=0;
    mDelaymS(30);                                                              //上电延时,等待内部晶振稳定,必加 
//  CfgFsys( );     
    
    P4_DIR |= bLED2;
    P3_DIR |= bTXD;
    mInitSTDIO( );                                                             //串口0,可以用于调试
    printf("start ...\n");  
	
    CH559SPI0HostInit();                                                       //SPI0主机模式初始化
#if SPI0Interrupt
    CH559SPI0InterruptInit();                                                  //SPI0中断初始化
    EA  = 1;                                                                   //使能全局中断
#endif
    while(1)
    {   
	      SCS = 0; 
        CH559SPI0Write(0x06);                                                  //CH559和CH376通讯
//		  flag = 0;
        mDelayuS(2);
        CH559SPI0Write(i);
        mDelayuS(2);
//		  flag = 1;
        TmpBuf = CH559SPI0Read();
        SCS = 1;
        if(TmpBuf != (i^0xff))
        {
            LED2 = !LED2;
		        printf("%02X  %02X  \n",(UINT16)i,(UINT16)TmpBuf);					
        }
		    mDelaymS(10);
				i = i+2;
    }
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值