电子工程网

标题: 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

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
1.jpg
作者: 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