电子工程网
标题:
51 模拟spi的程序
[打印本页]
作者:
wangkj
时间:
2009-7-10 10:01
标题:
51 模拟spi的程序
file:///C:/DOCUME%7E1/wang/LOCALS%7E1/Temp/moz-screenshot.jpg#include "upsd.h"
#define uchar unsigned char
#define uint unsigned int
#define WREN 0x06 // 写使能锁存指令
#define RDSR 0x05 // 读状态寄存器指令
#define WRSR 0x01 // 写状态寄存器指令
#define READ 0x03 // 读存储器阵列指令
#define WRITE 0x02 // 写存储器阵列指令
sbit _CS = P1^0; // SPI总线的片选信号线
sbit SCK = P1^1; // SPI总线的钟信号线
sbit SI = P1^2; // SPI总线的串行数据输入线
sbit SO = P1^3; // SPI总线的串行数据输出线
#define BUFFSIZE 16
uchar readbuff[BUFFSIZE],writebuff[BUFFSIZE]; // 读写缓冲区
/*从SPI总线上读入一个字节*/
uchar read(void)
{
uchar data i,inData;
for(i=0; i<8; i++) // 移8次
{
SCK = 0; // 拉低时钟线
inData <<= 1;
inData |= SO; // 从SPI总线的数据输出线SO上读入一位
SCK = 1; // 拉高时钟线
}
return(inData);
}
/*输出一个字节到SPI总线上*/
void write(uchar outData)
{
uchar data i;
for(i=0; i<8; i++) // 移8次
{
SCK = 0;
outData <<= 1;
SI = CY; // 移出一位,送出至SPI总线的数据输入线SI上
SCK = 1;
}
}/*读SPI器件的状态*/
uchar readSR(void)
{
uchar data SR_Data;
_CS = 0; // 选中器件
write(RDSR); // 发送读状态寄存器指令
SR_Data = read(); // 得状态值
_CS = 1; // 取消对器件的选定
return(SR_Data); // 送回状态值
}
/*写SPI器件的状态寄存器*/
void writeSR(uchar SR_Data) /*可以改变SPI器件看门狗时间,设定受保护阵列范围*/
{
_CS = 0;
write(WREN); // 发送使能锁存指令
_CS = 1;
_CS = 0;
write(WRSR); // 发送写状态寄存器指令
write(SR_Data); // 写入状态值
_CS = 1;
}
/*将一串数据写入指定的EEPROM阵列地址*/
void writeEEPROM(uint addr,len)
{
uchar data i,com;
_CS = 0;
write(WREN); //发送使能锁存指令
_CS = 1;
_CS = 0;
com = (addr>>8) & 0x08 | WRITE; DPL = addr;
write(com); // 发送读命令和目标地址的最高位A8
write(DPL); // 发送地址的低8位
for(i=0; i
);// 写字符串到X5043
_CS=1;
}
/*从指定的EEPROM阵列地址读出一串数据*/
void readEEPROM(uint addr,len)
{
uchar data i,com;
_CS = 0;
com = (addr>>8) & 0x08 | READ; DPL = addr;
write(com); // 发送读命令和目标地址的最高位A8
write(DPL); // 发送地址的低8位
for(i=0; i
=read();// 读入字符串
_CS = 1;
}
//**************************************************************************************************
xdata uchar CONTROL_B _at_ 0x803;
xdata uchar DATAOUT_B _at_ 0x805;
xdata uchar DIRECTION_B _at_ 0x807;
uchar position; // LED的位码存储单元
uchar a[8]; // 8字节长显示缓冲区
uchar *disp_ptr; // 显示缓冲区的指针
uchar code led_code[11] = {0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0xff};
//数字码表0-9,LED无显示时对应码值为0xff
/********LED显示的初始化********/
void led_init(void)
{
CONTROL_B = 0;
DATAOUT_B = 0;
DIRECTION_B = 0xff;
position = 0x80;
disp_ptr = &a;
}
/*1位LED显示,并更新位码和显示缓冲指针*/
void display(void)
{
P4 = 0xff;
DATAOUT_B = position;
position = position>>1;
if(position == 0) position = 0x80;
P4 = led_code[*disp_ptr++];
if(position == 0x80) disp_ptr = &a;
}
/*将一个无符号型整数的每位数据分别装载到显示缓冲区*/
void loadbuff(uint sum)
{
a[0] = sum/10000; a[1] = (sum%10000)/1000;
a[2] = (sum%1000)/100; a[3] = (sum%100)/10;
a[4] = sum%10; a[5] = 10; a[6] = 10;a[7] = 10;
}
//***************************************************************************************
#define TIMER0_COUNT 0xf8CD
// TH0=0xf8,TL0=0xcd,在11.0592MHz的晶振频率下,可实现2ms的计数
bit timer0int; // 2ms定时的标志位
/**********初始化定时器0**********/
void timer0_init(void)
{
TMOD &= 0xf0;
TMOD |= 0x01;
TL0 = (TIMER0_COUNT & 0x00ff);
TH0 = (TIMER0_COUNT >> 8);
PT0 = 0;
ET0 = 1;
TR0 = 1;
timer0int = 0;
}
/*定时器0的中断服务程序,每次中断置中断标志位*/
void timer0isr(void) interrupt 1
{
TL0 = TL0 + (TIMER0_COUNT & 0x00FF);
TH0 = TH0 + (TIMER0_COUNT >> 8);
timer0int = 1;
}
//***************************************************
bit okflag; // 外部脉冲计数加一标志
void int0_init(void)
{
IT0 = 1; // 边沿触发
EX0 = 1;
EA = 1; // 允许所有中断源
okflag = 0;
}
void int0isr(void) interrupt 0
{
okflag = 1;
}
//***********************************************************************
main()
{
uchar i = 0;uint sum;
WDKEY = 0x55; // 关看门狗定时器
writeSR(0x10); // 初始化X5043的状态寄存器
while((readSR()&0x01) == 1); // 等待X5043的非易失性写完成
readEEPROM(0x00,2); // 读入0x00和x01两个单元的内容
if((readbuff[0] == 0x55) && (readbuff[1] == 0xaa))
{ // 如果分别为0x55和0xaa,说明已经初始化过该芯片
readEEPROM(0x02,2); // 读出0x02和0x03两个单元的内容
sum = ((uint)readbuff[0]<<8)+readbuff[1];
// 根据0x02和0x03两个单元的内容初始化计数值
}
else
{ // 否则对芯片进行初始化
sum=0; // 初始化计数值为0
writebuff[0]=0x55;writebuff[1]=0xaa; //设定初始化标记为0x55,0xaa
writebuff[2]=0;writebuff[3]=0; // 初始化0x02和0x03两个单元的内容
writeEEPROM(0x00,4); // 写入初始化的设定字符串
}
loadbuff(sum);
led_init();
timer0_init();
int0_init();
for(;;)
{
if(timer0int)
{
timer0int=0;
display(); // 每2ms显示一位LED
if(okflag) // 如果脉冲计数值加一
{
if((readSR()&0x01)!=1) // X5043可写
{
okflag=0; // 清除okflag标志
sum++; // 计数加一
writebuff[0]=sum>>8; writebuff[1]=sum;
writeEEPROM(0x02,2); // 发送新的计数值
loadbuff(sum); // 装载显示缓冲
}
}
}
}
}
作者:
wangkj
时间:
2009-7-10 10:02
源码 rar文件。
C51-SPI.rar
2009-7-10 10:02 上传
点击文件名下载附件
下载积分: 积分 -1
2.53 KB, 下载积分: 积分 -1
作者:
node
时间:
2009-7-10 10:22
顶老王
作者:
Netjob
时间:
2009-7-10 11:06
路过~,顶一下。
作者:
诸葛孔明
时间:
2009-7-10 12:26
顶上,楼主辛苦
作者:
wangkj
时间:
2009-7-10 15:19
这个是俺搜出来的,写的最规范的。非原创。
作者:
老郭
时间:
2009-7-10 21:55
作者:
lelee007
时间:
2009-7-12 17:21
顽强地路过,并顶之
作者:
jeff
时间:
2010-7-2 17:55
好咚咚
作者:
wangkj
时间:
2010-7-2 19:14
我靠,挖坟啊。
不过,这个问题,很多人多次问过。
作者:
tkggwxfss
时间:
2010-7-11 11:51
谢谢啦
作者:
wangkj
时间:
2010-7-12 09:30
作者:
kevin_chan
时间:
2010-7-12 10:19
谢谢,受用了
作者:
ksf1006
时间:
2010-7-20 14:42
顶起来!!
作者:
solo_74
时间:
2010-8-17 10:34
看看,学习下!
作者:
wxw123321
时间:
2010-9-6 16:49
顶起
作者:
fymbl
时间:
2010-9-22 17:29
学习一下。
作者:
lising
时间:
2010-9-26 15:49
不错!顶
作者:
marjolein
时间:
2010-10-11 20:45
thanks
作者:
dalfer
时间:
2010-10-14 15:16
模拟的SPI让我头疼,显示接口的SPI操作不关定时器中断就不行,不然会显示乱码,没办法!
作者:
sdlyyy
时间:
2011-3-5 10:39
非常感谢,好好学习。
作者:
onlylord
时间:
2011-7-6 22:57
谢谢分享
作者:
wfnic
时间:
2011-7-10 10:06
hao1h
作者:
wlp267
时间:
2011-7-13 21:56
不错!顶
作者:
xzz88
时间:
2011-7-25 14:48
我需要一个~
作者:
xzz88
时间:
2011-7-25 14:51
我的分,怎么这么少了呢?
作者:
phil_guo
时间:
2011-9-14 00:42
作者:
ltt198511
时间:
2011-10-27 22:28
下来看看啊
作者:
linkai_joseph
时间:
2011-12-27 11:15
xiexielouzhule
作者:
guochangfei20
时间:
2012-2-15 13:05
不错不错,学习了。。。
作者:
此人较为厉害
时间:
2013-6-13 19:14
好东西,谢谢了
欢迎光临 电子工程网 (https://www.eechina.com/)
Powered by Discuz! X3.4