|
最近研究了一下AVR的SPI通信。因为自己是新手,在我找资料学习的时候碰到了不少障碍,网上找的好多例程通过仿真都或多或少都有些毛病,再此希望给那些和我一样正在学习SPI通信的朋友们一些帮助。实验很简单就是通过读取本机I/O状态通过SPI发送到对方用LED显示。Proteus仿真在附件里。是段全双工SPI通信。
注释不是很多希望大家参考芯片手册了学习。
主机:
#include<iom16v.h>
#include<macros.h>
#include<AVRdef.h>
#define uint unsigned int
#define uchar unsigned char
void spi_init(void);
uchar spi_transmit(uchar sData);
/**********************************************/
void spi_init(void) //spi初始化
{
PORTB=0XF0; //SCK MISO MOSI SS 使能上拉
DDRB=BIT(5)|BIT(7)|BIT(4);
SPCR=BIT(SPE)|BIT(MSTR)|BIT(SPR0);
}
/*************************************************/
/****************************************************/
uchar spi_transmit(uchar sData)//功能:使用SPI发送一个字节
{
uchar tep;
PORTB&=~BIT(4)//这个很重要,当初就是没仔细领悟芯片手册关于ss的解释导致我浪费了好多时间。
SPDR = sData;
while(!(SPSR & BIT(SPIF)));
PORTB|=BIT(4);
tep=SPDR;//读从机发回来的数据
return tep;
}
/*************************************************/
void main(void)
{
uchar led;
DDRC=0X00;
PORTC=0X00;
DDRA=0XFF;
PORTA=0X00;
spi_init();
while(1)
{
led = spi_transmit(PINC);
PORTA=led;
}
}
从机:
#include<iom16v.h>
#include<macros.h>
#include<AVRdef.h>
#define uint unsigned int
#define uchar unsigned char
#pragma interrupt_handler SIG_SPI:11//从机的中断,用于发送结束。
uchar temp=0x01;
void spi_init(void);
/**************************
函数名称:delay_ms
作用:毫秒延时函数
***************************/
void delay_ms(xms)
{
uchar i,j;
for(i=xms;i>0;i--)
for(j=1141;j>0;j--);
}
/***********************************************/
void spi_init(void) //spi初始化
{
DDRB=BIT(6);
PORTB=0XF0;
SPCR = BIT(SPE)|BIT(SPIE);
SEI();
}
/*************************************************/
void SIG_SPI(void) //一个字节发送或接收完成中断
{
temp=SPDR;
}
/***************************************************/
void main(void)
{
DDRC=0X00;
PORTC=0X00;
DDRA=0XFF;
PORTA=0X00;
spi_init();
while(1)
{
SPDR=PINC;
PORTA= temp;
}
}
ATmega8的例程我打包放附件里了。和16差不多就是SPI的接口不同,当时就是没仔细看芯片手册闹了不少笑话。仿真终究不是真的,现实中遇到的有些问题是仿真不出来的!
仿真 程序在里面ourdev_710554L4OCLA.zip(文件大小:153K) (原文件名:AVR单片机SPI通信带proteus仿真ICC编译.zip) |
|