[MCU] stm 8 spi

[复制链接]
2325|2
 楼主| suahatm 发表于 2013-9-23 16:28 | 显示全部楼层 |阅读模式
  1. 主机程序
  2. #include"iostm8s103k3.h"
  3. #include"uart1.h"
  4. void CLK_Init(void)
  5. {
  6.       CLK_CKDIVR_HSIDIV = 0;    //1分频
  7. }

  8. void GPIO_Init(void)
  9. {
  10.       /*一主一从高速模式(GPIO主模式)*/
  11.       PC_DDR=0x6f; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
  12.       PC_CR1=0x6f;
  13.       PC_CR2=0x60;
  14. }
  15. void SPI_Init(void)
  16. {
  17.       CLK_PCKENR1=0xff;//接通外设时钟门控制器
  18.       SPI_CR1=0x35;  
  19.       SPI_CR2=0x03;
  20.       SPI_CR1|=0x40;
  21.       /*高位先发,分频128,主机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
  22.       NSS管脚,禁止CRC*/
  23. }

  24. void delayus(void)   
  25. {   
  26.     asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns   
  27.     asm("nop");   
  28.     asm("nop");   
  29.     asm("nop");
  30. }
  31. /*---- 毫秒级延时程序---------------------*/  
  32. void delayms(unsigned int time)   
  33. {
  34.    unsigned int i;   
  35.    while(time--)     
  36.    for(i=4;i>0;i--)   
  37.     delayus();   
  38. }  
  39. void Write_Byte(uchar byte)
  40. {  
  41.   SPI_DR = byte;     /* 将发送的数据写到数据寄存器 */
  42.   delayus();
  43.   delayus();
  44.   delayus();
  45.   while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  46. }

  47. uchar Read_Write(uchar byte)
  48. {
  49.   uchar Rvalue;
  50.   while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  51.   delayus();
  52.   delayus();
  53.   SPI_DR =byte;      /*  发送一个无效字节,以产生接收时钟*/
  54.   while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
  55.   delayus();
  56.   delayus();
  57.   delayus();
  58.   Rvalue=SPI_DR;
  59.   return Rvalue;
  60. }

  61. int main(void)
  62. {
  63.     int k=0;
  64.     asm("sim");    //关总中断
  65.     uart1_init();
  66.     CLK_Init();
  67.     GPIO_Init();
  68.     SPI_Init();
  69.     asm("rim");    //开总中断
  70.     //Write_Byte(1);
  71.     Read_Write(0);
  72.     while(1)
  73.     {
  74.         k=Read_Write(11);
  75.         uart1_send(k);//通过UART口检测从机发送过来的
  76.         delayms(100);
  77.         k=Read_Write(15);
  78.         uart1_send(k); //通过UART口检测从机发送过来的
  79.         delayms(100);
  80.     }
  81. }

  82. //#pragma   vector = UART1_R_RXNE_vector
  83. //__interrupt void uart1rxd(void)
  84. //{
  85. //   data = UART1_DR;
  86. //}
  87. 从机程序
  88. #include"iostm8s103k3.h"
  89. #include"led.h"
  90. #include"delay.h"
  91. uint m,flag;
  92. void CLK_Init(void)
  93. {
  94.       CLK_CKDIVR_HSIDIV = 0;    //1分频
  95. }

  96. void GPIOC_Init(void)
  97. {
  98.       /*一主一从高速模式(GPIO从模式)*/
  99.       PC_DDR=0x8f; //MISO为为高速推挽输出,MISO为悬空输入,SCK悬空输入
  100.       PC_CR1=0x8f;
  101.       PC_CR2=0x80;  
  102. }
  103. void GPIO_Init(void)
  104. {
  105.       PB_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
  106.       PB_CR1=0xff;
  107.       PB_CR2=0x00;
  108.       PD_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
  109.       PD_CR1=0xff;
  110.       PD_CR2=0x00;
  111.       
  112. }
  113. void SPI_Init(void)
  114. {
  115. /*从模式SPI寄存器初始化*/
  116.       CLK_PCKENR1=0xff; //接通外设时钟门控制器
  117.       SPI_CR1=0x31;  
  118.       SPI_CR2=0x02;
  119.       SPI_CR1|=0x40;
  120.      /* 高位先发,分频128,从机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
  121.       NSS管脚,禁止CRC*/
  122. }
  123. void Write_Byte(uchar byte)
  124. {  
  125.   SPI_DR = byte;     /* 将发送的数据写到数据寄存器 */
  126.   while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  127. }

  128. uchar Read_Write(uchar byte)
  129. {
  130.   uchar Rvalue;
  131.   while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  132.   delayus();
  133.   SPI_DR = byte;      /*  发送一个无效字节,以产生接收时钟*/
  134.   while(!(SPI_SR & 0x01));              /* 等待接受寄存器满 */
  135.   delayus();
  136.   Rvalue=SPI_DR;
  137.   return Rvalue;
  138. }

  139. uchar Read_Byte()
  140. {
  141.   uint Rvalue;
  142.   while(!(SPI_SR & 0x01));              /* 等待接受寄存器满 */
  143.   delayus();
  144.   Rvalue=SPI_DR;
  145.   return Rvalue;
  146. }
  147. int main(void)
  148. {
  149.     asm("sim");    //关总中断
  150.     CLK_Init();
  151.     GPIOC_Init();
  152.     GPIO_Init();
  153.     SET_Init();
  154.     SPI_Init();
  155.     SPI_ICR=0X40;
  156.     asm("rim");    //开总中
  157.     while(1)
  158.     {
  159.       if(flag==1)
  160.       {
  161.         flag=0;
  162.         Write_Byte(m);
  163.         Display(1, m);
  164.       }

  165.     }
  166. }

  167. #pragma   vector = 0xC
  168. __interrupt void SPI_IRQHandler(void)
  169. {
  170.     if((SPI_SR&0x01)==1)
  171.     {
  172.       m=Read_Byte();
  173.       flag=1;
  174.     }

  175.     //add your code hered
  176. }
主机程序
#include"iostm8s103k3.h"
#include"uart1.h"
void CLK_Init(void)
{
      CLK_CKDIVR_HSIDIV = 0;    //1分频
}

void GPIO_Init(void)
{
      /*一主一从高速模式(GPIO主模式)*/
      PC_DDR=0x6f; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
      PC_CR1=0x6f;
      PC_CR2=0x60;
}
void SPI_Init(void)
{
      CLK_PCKENR1=0xff;//接通外设时钟门控制器
      SPI_CR1=0x35;  
      SPI_CR2=0x03;
      SPI_CR1|=0x40;
      /*高位先发,分频128,主机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
      NSS管脚,禁止CRC*/
}

void delayus(void)   
{   
    asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns   
    asm("nop");   
    asm("nop");   
    asm("nop");
}
/*---- 毫秒级延时程序---------------------*/  
void delayms(unsigned int time)   
{
   unsigned int i;   
   while(time--)     
   for(i=4;i>0;i--)   
    delayus();   
}  
void Write_Byte(uchar byte)
{  
  SPI_DR = byte;     /* 将发送的数据写到数据寄存器 */
  delayus();
  delayus();
  delayus();
  while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
}

uchar Read_Write(uchar byte)
{
  uchar Rvalue;
  while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  delayus();
  delayus();
  SPI_DR =byte;      /*  发送一个无效字节,以产生接收时钟*/
  while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
  delayus();
  delayus();
  delayus();
  Rvalue=SPI_DR;
  return Rvalue;
}

int main(void)
{
    int k=0;
    asm("sim");    //关总中断
    uart1_init();
    CLK_Init();
    GPIO_Init();
    SPI_Init();
    asm("rim");    //开总中断
    //Write_Byte(1);
    Read_Write(0);
    while(1)
    {
        k=Read_Write(11);
        uart1_send(k);//通过UART口检测从机发送过来的
        delayms(100);
        k=Read_Write(15);
        uart1_send(k); //通过UART口检测从机发送过来的
        delayms(100);
    }
}

//#pragma   vector = UART1_R_RXNE_vector
//__interrupt void uart1rxd(void)
//{
//   data = UART1_DR;
//}
从机程序
#include"iostm8s103k3.h"
#include"led.h"
#include"delay.h"
uint m,flag;
void CLK_Init(void)
{
      CLK_CKDIVR_HSIDIV = 0;    //1分频
}

void GPIOC_Init(void)
{
      /*一主一从高速模式(GPIO从模式)*/
      PC_DDR=0x8f; //MISO为为高速推挽输出,MISO为悬空输入,SCK悬空输入
      PC_CR1=0x8f;
      PC_CR2=0x80;  
}
void GPIO_Init(void)
{
      PB_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
      PB_CR1=0xff;
      PB_CR2=0x00;
      PD_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
      PD_CR1=0xff;
      PD_CR2=0x00;
      
}
void SPI_Init(void)
{
/*从模式SPI寄存器初始化*/
      CLK_PCKENR1=0xff; //接通外设时钟门控制器
      SPI_CR1=0x31;  
      SPI_CR2=0x02;
      SPI_CR1|=0x40;
     /* 高位先发,分频128,从机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
      NSS管脚,禁止CRC*/
}
void Write_Byte(uchar byte)
{  
  SPI_DR = byte;     /* 将发送的数据写到数据寄存器 */
  while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
}

uchar Read_Write(uchar byte)
{
  uchar Rvalue;
  while(!(SPI_SR & 0x02));              /* 等待发送寄存器为空 */
  delayus();
  SPI_DR = byte;      /*  发送一个无效字节,以产生接收时钟*/
  while(!(SPI_SR & 0x01));              /* 等待接受寄存器满 */
  delayus();
  Rvalue=SPI_DR;
  return Rvalue;
}

uchar Read_Byte()
{
  uint Rvalue;
  while(!(SPI_SR & 0x01));              /* 等待接受寄存器满 */
  delayus();
  Rvalue=SPI_DR;
  return Rvalue;
}
int main(void)
{
    asm("sim");    //关总中断
    CLK_Init();
    GPIOC_Init();
    GPIO_Init();
    SET_Init();
    SPI_Init();
    SPI_ICR=0X40;
    asm("rim");    //开总中
    while(1)
    {
      if(flag==1)
      {
        flag=0;
        Write_Byte(m);
        Display(1, m);
      }

    }
}

#pragma   vector = 0xC
__interrupt void SPI_IRQHandler(void)
{
    if((SPI_SR&0x01)==1)
    {
      m=Read_Byte();
      flag=1;
    }

    //add your code hered
}
其单步调试时,从机把主机发送过来的数发回主机。通过UART口显示到上位机上(串口调试助手)
其串口接收的数据如下;00 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F
从机display的函数显示也正常,但是一旦主机debeg全速运行就会出错
主机通过UART口显示的是0B和0F显示就会不对。从机display的函数显示就不正常了。
可能是延时时间也可能是全速运行时display显示的是一部分。本人是想先通过写一个函数数给从机数,从机应答。如果成功了想写一组数函数发送给从机。再就是随时在主机接收一个数,接收一直数。请教高人stm8 的spi硬件通信(不是通过模拟的),。谢谢
由于是新人没有太多分 请见谅

 楼主| suahatm 发表于 2013-9-28 15:11 | 显示全部楼层
后面自己想了想 果真是从机的display处理跟不上从机的接收数据
 楼主| suahatm 发表于 2013-9-28 15:14 | 显示全部楼层
但是现在在写主机 随时发送一组数据,随时接收一组数剧。碰到了主从握手言和的问题.有哪位兄弟哪呢过发个程序看看,连续接收三个数看是不是和自己定义的地址相符的判断程序
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

4

帖子

1

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