打印
[MCU]

stm 8 spi

[复制链接]
2081|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
suahatm|  楼主 | 2013-9-23 16:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
主机程序
#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
}
主机程序
#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

粉丝