51 模拟spi的程序
2009年07月10日 10:01 发布者:wangkj
#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,writebuff; // 读写缓冲区
/*从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
}
/*从指定的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
}
//**************************************************************************************************
xdata uchar CONTROL_B _at_ 0x803;
xdata uchar DATAOUT_B _at_ 0x805;
xdata uchar DIRECTION_B _at_ 0x807;
uchar position; // LED的位码存储单元
uchar a; // 8字节长显示缓冲区
uchar *disp_ptr; // 显示缓冲区的指针
uchar code led_code = {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 = sum/10000; a = (sum%10000)/1000;
a = (sum%1000)/100; a = (sum%100)/10;
a = sum%10; a = 10; a = 10;a = 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 == 0x55) && (readbuff == 0xaa))
{ // 如果分别为0x55和0xaa,说明已经初始化过该芯片
readEEPROM(0x02,2); // 读出0x02和0x03两个单元的内容
sum = ((uint)readbuff<<8)+readbuff;
// 根据0x02和0x03两个单元的内容初始化计数值
}
else
{ // 否则对芯片进行初始化
sum=0; // 初始化计数值为0
writebuff=0x55;writebuff=0xaa; //设定初始化标记为0x55,0xaa
writebuff=0;writebuff=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=sum>>8; writebuff=sum;
writeEEPROM(0x02,2); // 发送新的计数值
loadbuff(sum); // 装载显示缓冲
}
}
}
}
}
网友评论
node 2009年07月10日
顶老王
顶老王
Netjob 2009年07月10日
路过~,顶一下。
路过~,顶一下。
诸葛孔明 2009年07月10日
顶上,楼主辛苦
顶上,楼主辛苦
wangkj 2009年07月10日
这个是俺搜出来的,写的最规范的。非原创。
这个是俺搜出来的,写的最规范的。非原创。
老郭 2009年07月10日
1489
1489
lelee007 2009年07月12日
顽强地路过,并顶之;P
顽强地路过,并顶之;P
jeff 2010年07月02日
好咚咚
好咚咚
wangkj 2010年07月02日
我靠,挖坟啊。
不过,这个问题,很多人多次问过。
我靠,挖坟啊。
不过,这个问题,很多人多次问过。
tkggwxfss 2010年07月11日
谢谢啦
谢谢啦
wangkj 2010年07月12日
:)
:)
kevin_chan 2010年07月12日
谢谢,受用了
谢谢,受用了
ksf1006 2010年07月20日
顶起来!!
顶起来!!
solo_74 2010年08月17日
看看,学习下!:)
看看,学习下!:)
wxw123321 2010年09月06日
顶起
顶起
fymbl 2010年09月22日
学习一下。
学习一下。
lising 2010年09月26日
不错!顶
不错!顶
marjolein 2010年10月11日
thanks
thanks
dalfer 2010年10月14日
模拟的SPI让我头疼,显示接口的SPI操作不关定时器中断就不行,不然会显示乱码,没办法!
模拟的SPI让我头疼,显示接口的SPI操作不关定时器中断就不行,不然会显示乱码,没办法!
sdlyyy 2011年03月05日
非常感谢,好好学习。
非常感谢,好好学习。
onlylord 2011年07月06日
谢谢分享
谢谢分享
wfnic 2011年07月10日
hao1h
hao1h
wlp267 2011年07月13日
不错!顶
不错!顶
xzz88 2011年07月25日
我需要一个~
我需要一个~
xzz88 2011年07月25日
我的分,怎么这么少了呢?
我的分,怎么这么少了呢?
phil_guo 2011年09月14日
:victory:
:victory:
ltt198511 2011年10月27日
下来看看啊
下来看看啊
linkai_joseph 2011年12月27日
xiexielouzhule
xiexielouzhule
guochangfei20 2012年02月15日
不错不错,学习了。。。
不错不错,学习了。。。
此人较为厉害 2013年06月13日
好东西,谢谢了
好东西,谢谢了

源码 rar文件。