[DemoCode下载] M051 spi程序

[复制链接]
1507|3
 楼主| 奥德赛 发表于 2016-2-15 19:55 | 显示全部楼层 |阅读模式


  1. #include "SPI.h"
  2. #define DEBUGMSG printf
  3. STATIC UINT32  g_unSpi0Rx0Data = 0, g_unSpi1Rx0Data = 0;
  4. /****************************************
  5. *函数名称:Spi0MasterInit
  6. *输    入:无
  7. *输    出:无
  8. *功    能:SPI0初始化为主机模式
  9. ******************************************/
  10. VOID Spi0MasterInit(VOID)
  11. {                                    
  12.     P1_MFP &= ~(P14_AIN4_SPI0SS | P15_AIN5_SPI0MOSI | P16_AIN6_SPI0MISO | P17_AIN7_SPI0CLK);
  13. P1_MFP |= (SPI0SS | SPI0MOSI | SPI0MISO | SPI0CLK) ;      //使能SPI0相关引脚
  14. ENABLE_SPI0_CLK;         //SPI0时钟使能                  
  15.     SPI0_SSR &= ~LVL_H;           //从机选择选择信号通过低电平激活
  16.     SPI0_CNTRL &= ~LSB_FIRST;    //优先发送/接收最高有效位
  17.     SPI0_CNTRL &= ~CLKP_IDLE_H;      //SCLK空闲时为低电平
  18.     SPI0_CNTRL |= TX_NEG_F;       //SDO 信号在SPICLK的下降沿改变
  19.     SPI0_CNTRL &= ~RX_NEG_F;       //SDI 信号在SPICLK上升沿锁存
  20.     CLKDIV &= 0xFFFFFFF0;               //HCLK_N = 0, Pclk = SYSclk/(HCLK_N+1)
  21.     SPI0_DIVIDER &= 0xFFFF0000;         //SPIclk = Pclk/((HCLK_N+1)*2)
  22.     SPI0_DIVIDER |= 0x00000002;   
  23.     SET_SPI0_MASTER_MODE;            //SPI0工作在主机模式
  24.     ENABLE_SPI0_AUTO_SLAVE_SLECT;    //使能自动从机选择
  25.     SPI0_SSR |= SSR_ACT;     
  26. }
  27. /****************************************
  28. *函数名称:Spi0Send1W
  29. *输    入:ulData    发送的数据
  30.           ucLength  数据长度
  31. *输    出:无
  32. *功    能:SPI0发送数据
  33. ******************************************/
  34. VOID Spi0Send1W(UINT32 ulData, UINT8 ucLength)
  35. {
  36.     SPI0_CNTRL &= TX_NUM_ONE;      
  37.     Spi0Length(ucLength);
  38.     SPI0_TX0 = ulData;
  39.     SPI0_CNTRL |= GO_BUSY;         
  40. }



  41. /****************************************
  42. *函数名称:GetSlaveID
  43. *输    入:无
  44. *输    出:无
  45. *功    能:获取从机ID
  46. ******************************************/
  47. VOID GetSlaveID(VOID)
  48. {
  49.     Spi0Send1W(0x00000055, 0x08);
  50.     while((SPI0_CNTRL & GO_BUSY)!=0);

  51.     Spi0Send1W(0x00000000, 0x08);
  52.     while((SPI0_CNTRL & GO_BUSY)!=0);
  53.     g_unSpi0Rx0Data = SPI0_RX0;
  54. }
  55. /****************************************
  56. *函数名称:Spi0Length
  57. *输    入:ucLength 数据长度
  58. *输    出:无
  59. *功    能:设置SPI0数据长度
  60. ******************************************/
  61. VOID Spi0Length(UINT8 ucLength)
  62. {
  63.      if(ucLength <= 0x20)
  64.     {
  65.         if((ucLength & 0x01) == 0)
  66.             SPI0_CNTRL &= ~(1<<3);
  67.         else
  68.             SPI0_CNTRL |= (1<<3);
  69.         if((ucLength & 0x02) == 0)
  70.             SPI0_CNTRL &= ~(1<<4);
  71.         else
  72.             SPI0_CNTRL |= (1<<4);

  73.         if((ucLength & 0x04) == 0)
  74.             SPI0_CNTRL &= ~(1<<5);
  75.         else
  76.             SPI0_CNTRL |= (1<<5);

  77.         if((ucLength & 0x08) == 0)
  78.             SPI0_CNTRL &= ~(1<<6);
  79.         else
  80.             SPI0_CNTRL |= (1<<6);

  81.         if((ucLength & 0x10) == 0)
  82.             SPI0_CNTRL &= ~(1<<7);
  83.         else
  84.             SPI0_CNTRL |= (1<<7);
  85.     }
  86. }
  87. /****************************************
  88. *函数名称:Spi1SlaveInit
  89. *输    入:无
  90. *输    出:无
  91. *功    能:SPI1初始化为从机
  92. ******************************************/
  93. VOID Spi1SlaveInit(VOID)
  94. {                              
  95.     P0_MFP &= ~(P04_AD4_SPI1SS | P05_AD5_SPI1MOSI | P06_AD6_SPI1MISO | P07_AD7_SPI1CLK);

  96. P0_MFP |= (SPI1SS | SPI1MOSI | SPI1MISO | SPI1CLK) ;      //使能SPI1相关引脚
  97. ENABLE_SPI1_CLK;
  98. SPI1_SSR &= LTRIG_EDG;         //从机输入边沿触发
  99.     SPI1_SSR &= ~LVL_H;          //从机选择选择信号通过低电平激活

  100.     SPI1_CNTRL &= ~LSB_FIRST;      //优先发送/接收最高有效位
  101.     SPI1_CNTRL &= ~CLKP_IDLE_H;      //SCLK空闲时为低电平
  102.     SPI1_CNTRL |= TX_NEG_F;       //SDO 信号在SPICLK的下降沿改变
  103.     SPI1_CNTRL &= ~RX_NEG_F;       //SDI 信号在SPICLK上升沿锁存

  104.     CLKDIV &= 0xFFFFFFF0;               //HCLK_N = 0, Pclk = SYSclk/(HCLK_N+1)
  105.     SPI1_DIVIDER &= 0xFFFF0000;         //SPIclk = Pclk/((HCLK_N+1)*2)
  106.     SPI1_DIVIDER |= 0x00000002;
  107.     SET_SPI1_SLAVE_MODE;          //SPI1工作在从机模式
  108.    
  109.     ENABLE_SPI1_INTERRUPT;        //使能SPI1中断
  110.     NVIC_ISER |= SPI1_INT;      
  111.     Spi1Length(8);         //设置SPI1数据长度
  112.     SPI1_GO_BUSY;                 //等待SPI1 RX0接收信号
  113. }  
  114. /****************************************
  115. *函数名称:Spi1Length
  116. *输    入:ucLength 数据长度
  117. *输    出:无
  118. *功    能:设置SPI1数据长度
  119. ******************************************/
  120. VOID Spi1Length(UINT8 ucLength)
  121. {
  122.      if(ucLength <= 0x20)
  123.     {
  124.         if((ucLength & 0x01) == 0)
  125.             SPI1_CNTRL &= ~(1<<3);
  126.         else
  127.             SPI1_CNTRL |= (1<<3);
  128.         if((ucLength & 0x02) == 0)
  129.             SPI1_CNTRL &= ~(1<<4);
  130.         else
  131.             SPI1_CNTRL |= (1<<4);

  132.         if((ucLength & 0x04) == 0)
  133.             SPI1_CNTRL &= ~(1<<5);
  134.         else
  135.             SPI1_CNTRL |= (1<<5);

  136.         if((ucLength & 0x08) == 0)
  137.             SPI1_CNTRL &= ~(1<<6);
  138.         else
  139.             SPI1_CNTRL |= (1<<6);

  140.         if((ucLength & 0x10) == 0)
  141.             SPI1_CNTRL &= ~(1<<7);
  142.         else
  143.             SPI1_CNTRL |= (1<<7);
  144.     }
  145. }
  146. /****************************************
  147. *函数名称:PrintGetData
  148. *输    入:无
  149. *输    出:无
  150. *功    能:打印SPI0/1接收到的数据
  151. ******************************************/
  152. VOID PrintGetData(VOID)
  153. {
  154.     DEBUGMSG("Slave Get Command = %X\n", g_unSpi1Rx0Data);
  155.     DEBUGMSG("Master Get Feed Back Data = %X\n", g_unSpi0Rx0Data);
  156. }
  157. /*****************************************
  158. *函数名称:SPI1_IRQHandler
  159. *输    入:无
  160. *输    出:无
  161. *功    能:SPI1中断服务函数
  162. ******************************************/
  163. VOID SPI1_IRQHandler(VOID)
  164. {
  165.     SPI1_CNTRL |= SPI_IF;       //清除中断标志
  166.     if(SPI1_RX0 == 0x55)
  167.     {
  168.         g_unSpi1Rx0Data = SPI1_RX0;
  169.         SPI1_TX0 = 0x000000DA;
  170.     }
  171.     else
  172.         SPI1_TX0 = 0x00000000;
  173.     SPI1_GO_BUSY;                //等待SPI1 RX0接收信号
  174. }
  175. /****************************************
  176. *函数名称:main
  177. *输    入:无
  178. *输    出:无
  179. *功    能:函数主体
  180. ******************************************/
  181. INT32 main(VOID)
  182. {
  183.     PROTECT_REG                //ISP下载时保护FLASH存储器
  184. (
  185.    PWRCON |= XTL12M_EN;      //默认时钟源为外部晶振
  186.    while((CLKSTATUS & XTL12M_STB) == 0);   //等待12MHz时钟稳定  
  187.       CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M; //设置外部晶振为系统时钟
  188. )
  189. UartInit(12000000,9600);      //波特率设置为9600bps
  190.     Spi0MasterInit();        //SPI0初始化为主机模式
  191.     Spi1SlaveInit();        //SPI1初始化为从机模式   
  192.     while(1)
  193.     {
  194.         DEBUGMSG("Master will send 0x55 data to slave and receive 0xDA data\r\n");
  195.         DEBUGMSG("Put AnyKey to Start Test\r\n");
  196.         GetSlaveID();
  197.         PrintGetData();
  198.         printf("\r\n\r\n");
  199.   Delayms(1000);
  200.     }
  201. }


dongnanxibei 发表于 2016-2-16 11:30 | 显示全部楼层
VOID Spi0MasterInit(VOID)
{                                    
    P1_MFP &= ~(P14_AIN4_SPI0SS | P15_AIN5_SPI0MOSI | P16_AIN6_SPI0MISO | P17_AIN7_SPI0CLK);
P1_MFP |= (SPI0SS | SPI0MOSI | SPI0MISO | SPI0CLK) ;      //使能SPI0相关引脚
ENABLE_SPI0_CLK;         //SPI0时钟使能                  
    SPI0_SSR &= ~LVL_H;           //从机选择选择信号通过低电平激活
    SPI0_CNTRL &= ~LSB_FIRST;    //优先发送/接收最高有效位
    SPI0_CNTRL &= ~CLKP_IDLE_H;      //SCLK空闲时为低电平
    SPI0_CNTRL |= TX_NEG_F;       //SDO 信号在SPICLK的下降沿改变
    SPI0_CNTRL &= ~RX_NEG_F;       //SDI 信号在SPICLK上升沿锁存
    CLKDIV &= 0xFFFFFFF0;               //HCLK_N = 0, Pclk = SYSclk/(HCLK_N+1)
    SPI0_DIVIDER &= 0xFFFF0000;         //SPIclk = Pclk/((HCLK_N+1)*2)
    SPI0_DIVIDER |= 0x00000002;   
    SET_SPI0_MASTER_MODE;            //SPI0工作在主机模式
    ENABLE_SPI0_AUTO_SLAVE_SLECT;    //使能自动从机选择
    SPI0_SSR |= SSR_ACT;     
}

这是最难的地方
quray1985 发表于 2016-2-17 20:23 | 显示全部楼层
dongnanxibei 发表于 2016-2-16 11:30
VOID Spi0MasterInit(VOID)
{                                    
    P1_MFP &= ~(P14_AIN4_SPI0SS | P1 ...

SPI最难之处就是在时序方面,不好判别上升沿还是下降沿
secretuniverse 发表于 2016-2-27 20:57 | 显示全部楼层
为什么我设置SPI的时候完全按照datasheet上的时序设置的时候会出现问题呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

397

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部