搜索
bottom↓
回复: 17

AVR-ATmega16 SPI-双机通信程序

[复制链接]

出0入0汤圆

发表于 2010-7-9 15:07:11 | 显示全部楼层 |阅读模式
历时3天(由于第一天去研究所帮忙3/4天,第二天拆解彩电用去3/4天,其实也不算3天)的双机通信终于结束了,做到第三天晚上的时候,终于发现是一个悲剧。哎,其实我第一天就做出来了,是硬件的问题啊,导致我又十分郁闷的又多调试了2天,杯具啊。今天下午的时候,我就在想,程序是一定没有问题的,那么肯定是硬件出了问题。教训是十分深刻的。以后考虑要全面,不仅仅要考虑主观因素,也要考虑客观因素,两者的侧重不能偏离的太远,否则,是会出现悲剧的。

以下是源程序,给后来人以参考;

主机:

//SPI双机通信 主机
//发送0x09,接收方PD0~3,对应点小灯

//包含所需头文件
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
// SS   PB4
// MOSI PB5
// MISO PB6
// SCK PB7
/*------宏定义------*/
#define uchar unsigned char
#define uint unsigned int
#define BIT(x) (1<<(x))
#define NOP() asm("nop")
#define WDR() asm("wdr")

/*------函数定义------*/
void spi_write(uchar sData);
uchar spi_read(void);

//端口初始化
void port_init(void)
{
   DDRD = 0XFF;
   PORTB=PORTB|0b11110000; //SCK MISO MOSI SS 使能上拉     
   DDRB=DDRB&0b10111111;   //MISO 置为输入
   DDRB=DDRB|0b10110001;   //SCK MOSI SS 置为输出
     
}


void spi_init(void) //spi初始化
{   
   DDRB|=(~(1<<PB5))|(1<<PB7)|(1<<PB4)|(~(1<<PB4));
   SPCR = 0xF1;
   SPSR = 0x01;
}


SIGNAL(SIG_SPI) //一个字节发送或接收完成中断
{
   PORTD=SPDR;
}


void spi_write(uchar sData)//功能:使用SPI发送一个字节
{
   SPDR = sData;
   while(!(SPSR & BIT(SPIF)));
   //sData=SPDR;//读从机发回来的数据
}


uchar spi_read(void)//功能:使用SPI接收一个字节
{
   SPDR = 0x00;
   while(!(SPSR & BIT(SPIF)));
   return SPDR;
}


void init_devices(void)
{
   cli(); //禁止所有中断
   MCUCR = 0x00;
   MCUCSR = 0x80;//禁止JTAG
   GICR   = 0x00;
   port_init();
   spi_init();
   sei();//开全局中断
}
//主函数
int main(void)
{
   init_devices();
   spi_write(0X09);
   while(1)
   {
    NOP();
   }
   return 0;
}




从机:

//SPI双机通信 从机
//发送0x06,PA0~3接收
//包含所需头文件
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

/*------宏定义------*/
#define uchar unsigned char
#define uint unsigned int
#define BIT(x) (1<<(x))
#define NOP() asm("nop")
#define WDR() asm("wdr")

/*------函数定义------*/
void spi_write(uchar sData);
uchar spi_read(void);

//端口初始化
void port_init(void)
{
   DDRA = 0XFF;
   PORTB=PORTB|0b11110000; //SCK MISO MOSI SS 使能上拉     
   DDRB=DDRB&0b01001111;   // SCK MOSI SS 置为输入
   DDRB=DDRB|0b01000001;   // MISO 置为输出
}

void spi_init(void) //spi初始化
{
   DDRB|=(1<<PB5)|(~(1<<PB7))|(~(1<<PB4))|(~(1<<PB4));
   SPCR = 0xE1;
   SPSR = 0x00;
}

SIGNAL(SIG_SPI) //一个字节发送或接收完成中断
{
   DDRA=0XFF;
   PORTA=spi_read();
}

//功能:使用SPI发送一个字节
void spi_write(uchar sData)
{
   SPDR = sData;
   while(!(SPSR & BIT(SPIF)));
   //sData=SPDR;//读从机发回来的数据
}


//功能:使用SPI接收一个字节
uchar spi_read(void)
{
   SPDR = 0x00;
   while(!(SPSR & BIT(SPIF)));
   return SPDR;
}


void init_devices(void)
{
   cli(); //禁止所有中断
   MCUCR = 0x00;
   MCUCSR = 0x80;//禁止JTAG
   GICR   = 0x00;
   port_init();
   spi_init();
   sei();//开全局中断
}
//主函数
int main(void)
{
   init_devices();
   spi_write(0X06);

   while(1)
   {
    NOP();
   }
   return 0;
}



以下是源文件和仿真文件点击此处下载 ourdev_566813TGM0IY.rar(文件大小:14K) (原文件名:SPI双机通信.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-7-17 16:12:40 | 显示全部楼层
回复【楼主位】change1
--------------------------------------------------------------------
你好!你的主机程序里面这个函数是证明调用的?

uchar spi_read(void)//功能:使用SPI接收一个字节
{
   SPDR = 0x00;
   while(!(SPSR & BIT(SPIF)));
   return SPDR;
}


从机:

//功能:使用SPI接收一个字节
在uchar spi_read(void)
{
   SPDR = 0x00;
   while(!(SPSR & BIT(SPIF)));
   return SPDR;
}  的  SPDR = 0x00;什么意思?


我也写了一个双机通信的例程,我里面的要求是,主机每隔500ms发送数组的数据给从机,从机收到后则发送应答信号,数组的数据分别在主机和从机的数码管上显示,如果看到主机和从机的数码管显示值相同,则证明通信正常,但结果从机总是比主机慢半拍,麻烦你帮我看看。

出0入0汤圆

发表于 2010-7-17 16:25:59 | 显示全部楼层
主机

#include<iom16v.h>
#include<macros.h>
#define uint unsigned int
#define uchar unsigned char
#define xtal 8
#define CLR_BIT(x,y) (x&=~(1<<y))
#define SET_BIT(x,y) (x|=(1<<y))
#define SS 4
uchar seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar txbuffer[10]={0,1,2,3,4,5,6,7,8,9};
uchar i=0;
uchar temp;
void delay_ms(void)
{
  uint i;
  for(i=1;i<(uint)(xtal*143-2);i++);
}  

void delay_nms(uint k)
{
  uint i=0;
  while(i<k)
  {
    delay_ms();
        i++;
  }
}         

void port_init(void)
{
  DDRA=0xff;
  PORTA=0xff;
  DDRB=0xb0;
  PORTB=0x10;
  DDRC=0xff;
  PORTC=0xff;
}

void spi_masterinit(void)
{
  SPCR=0x51;
}   
  

void spi_mastertransmit(uchar data)
{
  SPDR=data;
  while(!(SPSR&(1<<SPIF)));
  CLR_BIT(SPSR,SPIF);
}

uchar spi_slavereceive(void)
{
   while(!(SPSR&(1<<SPIF)));
   return SPDR;
   CLR_BIT(SPSR,SPIF);
}   
  


void main(void)
{
  delay_nms(100);
  port_init();
  spi_masterinit();
  while(1)
  {
     CLR_BIT(PORTB,SS);
     spi_mastertransmit(txbuffer);
         SET_BIT(PORTB,SS);
          PORTC=0xff;
          PORTA=seg[txbuffer];
          PORTC=0xfe;
         delay_nms(500);
         if(++i>9)i=0;
  }
}         


从机

#include<iom16v.h>
#include<macros.h>
#define uint unsigned int
#define uchar unsigned char
#define CLR_BIT(x,y) (x&=~(1<<y))
#define xtal 8
uchar seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar rxbuffer[10];
uchar i=0;

void delay_ms(void)
{
  uint i;
  for(i=1;i<(uint)(xtal*143-2);i++);
}  

void delay_nms(uint k)
{
  uint i=0;
  while(i<k)
  {
    delay_ms();
        i++;
  }
}         

void port_init(void)
{
  DDRA=0xff;
  PORTA=0x00;
  DDRB=0x40;
  PORTB=0x10;
  DDRC=0xff;
  PORTC=0xff;
}

void spi_slaveinit(void)
{
  SPCR=0x41;
}

uchar spi_slavereceive()
{
  while(!(SPSR&(1<<SPIF)));
  return SPDR;
  CLR_BIT(SPSR,SPIF);
}  
  

void main(void)
{
  //delay_nms(50);
  port_init();
  spi_slaveinit();
  SPDR=0x55;
  while(1)
  {
    rxbuffer=spi_slavereceive();
        SPDR=0x55;
        PORTA=seg[rxbuffer];
        PORTC=0xfe;
        if(++i>9)i=0;
  }
}            
   

你在protues里仿真一下吧!数码管用的是共阳极,晶振8M

出0入0汤圆

发表于 2010-7-17 16:27:39 | 显示全部楼层
刚才打错了,数码管是共阴极。

出0入0汤圆

发表于 2010-7-17 21:35:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-18 18:05:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-10 11:01:32 | 显示全部楼层
呵呵,我刚好学习SPI双机通信...谢谢楼主分享~~~~

出0入0汤圆

发表于 2010-8-10 18:53:20 | 显示全部楼层
mark!

出0入0汤圆

发表于 2010-8-10 19:06:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-14 10:31:44 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-10-5 19:42:14 | 显示全部楼层
回复【2楼】fanwuye
主机
#include&lt;iom16v.h&gt;
#include&lt;macros.h&gt;
#define uint unsigned int
#define uchar unsigned char
#define xtal 8
#define clr_bit(x,y) (x&amp;=~(1&lt;&lt;y))
#define set_bit(x,y) (x|=(1&lt;&lt;y))
#define ss 4
uchar seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar txbuffer[10]={0,1,2,3,4,5,6,7,8,9};
uchar i=0;
uchar temp;
void delay_ms(void)
{
  uint i;
  ......
-----------------------------------------------------------------------

非常不好意思,由于近段时间太忙,我一直没上论坛。我QQ731424304,以后多多交流啊

出0入0汤圆

发表于 2010-11-28 18:19:07 | 显示全部楼层
刚好在学习spi通信,谢谢楼主分享

出0入0汤圆

发表于 2011-11-30 17:11:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-30 18:27:20 | 显示全部楼层
厉害,呵呵,复制,学习一下啊

出0入0汤圆

发表于 2013-9-10 21:57:14 | 显示全部楼层
不懂哇         

出0入0汤圆

发表于 2015-10-15 15:14:37 | 显示全部楼层
最经学习SPI双机通信,不知道为啥从机慢半拍,找到此帖可帮我大忙啊!

出0入0汤圆

发表于 2016-2-26 17:19:55 | 显示全部楼层
标记一下主从机通讯,晚上回家继续研究,不是故意挖坟
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-12 02:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表