参照着马老师的spi例子写的,但是有些问题,请老师看看
参照着马老师的spi例子写的,但是有些问题,请老师看看。主从机能收能发,但是收发的数据好像不对,开始用液晶调试的,发现从机液晶显示错误,但是返回给主机的数据是对的。后来怀疑是液晶速度跟不上,改用串口来显示数据,发现从机接收到的都是0,我是初学者,自己实在找不出问题所在。请马老师有空的时候帮忙看一下,谢谢。主机部分:
#include <iom64v.h>
#include <macros.h>
#include "1602.h"
#include "delay.h"
#define SIZE 100
unsigned char SPI_rx_buff; //收信箱
unsigned char SPI_tx_buff; //发信箱
unsigned char rx_wr_index; //收信箱写指针
unsigned char rx_rd_index; //收信箱读指针
unsigned char rx_counter; //收信箱存量
unsigned char rx_buffer_overflow; //收信箱满标志
unsigned char tx_wr_index; //发信箱写指针
unsigned char tx_rd_index; //发信箱读指针
unsigned char tx_counter; //发信箱存量
unsigned char SPI_ok=1;
#pragma interrupt_handler spi_stc_isr:18
void spi_stc_isr(void)
{
SPI_ok = 1; // SPI 空闲
SPI_rx_buff = SPDR; //从ISP口读出收到的字节
if (++rx_wr_index == SIZE) rx_wr_index = 0; //如果收信箱满则指针归零
if (++rx_counter == SIZE)
{
rx_counter = 0; //收信箱清空
rx_buffer_overflow = 1; //置满标志位
}
if (tx_counter) //如果发送缓冲区中有待发的数据
{
--tx_counter; //发送一个字节数据,存量减1
SPDR = SPI_tx_buff;
if (++tx_rd_index == SIZE) tx_rd_index = 0; //发信箱发完后读指针归零
SPI_ok = 0; //SPI忙
}
}
unsigned char getSPIchar(void)
{
unsigned char data;
while (rx_counter == 0); //收信箱空则等待
data = SPI_rx_buff; //从接收缓冲区取出一个SPI收到的数据
if (++rx_rd_index == SIZE) rx_rd_index = 0; //调整指针
CLI();
--rx_counter;
SEI();
return data;
}
void putSPIchar(char c)
{
while (tx_counter == SIZE); //发信箱满,等待
CLI();
if (tx_counter || SPI_ok==0) //发送缓冲区已中有待发数据
{
SPI_tx_buff = c; //将数据放入发信箱排队
if (++tx_wr_index == SIZE) tx_wr_index = 0; //调整指针
++tx_counter;
}
else
{
SPDR = c; //发送缓冲区中空且SPI口空闲,直接放入SPDR由SIP口发送
SPI_ok = 0;
}
SEI();
}
void putSPIstring(unsigned char *ptr)
{
while(*ptr)putSPIchar(*ptr++);
}
void spi_init(void)
{
unsigned char temp;
DDRB |= 0x07; //MISO=input and MOSI,SCK,SS = output
PORTB |= 0x08; //MISO上拉电阻有效,ss拉低输出
SPCR = 0xD5; //SPI允许,主机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率
SPSR = 0x00;
temp = SPSR;
temp = SPDR; //清空SPI,和中断标志,使SPI空闲
}
void main(void)
{
unsigned char i=0,j;
LCD_init();
CLI(); //关中断
spi_init(); //初始化SPI接口
SEI(); //开中断
putSPIstring("0123456789");
while(1)
{
//发送一个字节
//i++;
//LCD_write_char(0,0,i);
// getSPIchar(); //接收一个字节(第一个字节为空字节?
i=j;
j=getSPIchar();
if(i!=j)
LCD_write_data(j);
}
}
从机部分:
#include <iom64v.h>
#include <macros.h>
#include "1602.h"
#include "delay.h"
#define SIZE 100
unsigned char SPI_rx_buff; //收信箱
unsigned char SPI_tx_buff; //发信箱
unsigned char rx_wr_index; //收信箱写指针
unsigned char rx_rd_index; //收信箱读指针
unsigned char rx_counter; //收信箱存量
unsigned char rx_buffer_overflow; //收信箱满标志
unsigned char tx_wr_index; //发信箱写指针
unsigned char tx_rd_index; //发信箱读指针
unsigned char tx_counter; //发信箱存量
unsigned char SPI_ok=1;
#pragma interrupt_handler spi_stc_isr:18
void spi_stc_isr(void)
{
SPI_rx_buff = SPDR; //从ISP口读出收到的字节
SPI_ok = 1; // SPI 空闲
if (++rx_wr_index == SIZE) rx_wr_index = 0; //如果收信箱满则指针归零
if (++rx_counter == SIZE)
{
rx_counter = 0; //收信箱清空
rx_buffer_overflow = 1; //置满标志位
}
if (tx_counter) //如果发送缓冲区中有待发的数据
{
--tx_counter; //发送一个字节数据,存量减1
SPDR = SPI_tx_buff;
if (++tx_rd_index == SIZE) tx_rd_index = 0; //收信箱读完后读指针归零
SPI_ok = 0;
}
}
unsigned char getSPIchar(void)
{
unsigned char data;
while (rx_counter == 0); //收信箱空则等待
data = SPI_rx_buff; //从接收缓冲区取出一个SPI收到的数据
if (++rx_rd_index == SIZE) rx_rd_index = 0; //调整指针
CLI();
--rx_counter;
SEI();
return data;
}
//从机不能主动发数据,所以所有数据放发信箱里等待主机发信息来后回复过去
void putSPIchar(char c)
{
while (tx_counter == SIZE); //发信箱满,等待
CLI();
SPI_tx_buff = c; //将数据放入发信箱排队
if (++tx_wr_index == SIZE) tx_wr_index = 0; //调整指针
++tx_counter;
SEI();
}
void putSPIstring(unsigned char *ptr)
{
while(*ptr)putSPIchar(*ptr++);
}
void spi_init(void)
{
unsigned char temp;
DDRB |= 0x08; //MISO=output and MOSI,SCK,SS = input
PORTB|= 0x07; //MOSI,SCK,SS上拉电阻有效
SPCR = 0xC5; //SPI允许,从机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率
SPSR = 0x00;
temp = SPSR;
temp = SPDR; //清空SPI,和中断标志,使SPI空闲
}
void main(void)
{
unsigned char i=0;
LCD_init();
CLI(); //关中断
spi_init(); //初始化SPI接口
SEI(); //开中断
while(1)
{
i=getSPIchar(); //接收一个字节(第一个字节为空字节)
LCD_write_data(i);
putSPIchar(i); //发送一个字节
}
}
完整程序:
点击此处下载armok01167278.rar 把端口用电阻上拉到“1”(输出断开),看输入是不是FF,如果不是,检查程序;如果是,查硬件
页:
[1]