查看: 9950|回复: 30

51 模拟spi的程序 [复制链接]

wangkj (离线)
积分
57305
帖子
3129
发表于 2009-7-10 10:01:29 |显示全部楼层
关键词: spi , 程序 , 模拟
#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<len; i++)    write(writebuff);// 写字符串到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<len; i++)    readbuff=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 (离线)
积分
57305
帖子
3129
发表于 2009-7-10 10:02:22 |显示全部楼层
源码 rar文件。

C51-SPI.rar

2.53 KB, 下载次数: 290, 下载积分: 积分 -1

node (离线)
积分
25746
帖子
1101
发表于 2009-7-10 10:22:18 |显示全部楼层
顶老王
电工可以不理整治,但整治绝不会不理电工;
涉及到每个人的公共政策就是整治。
税收是每个公民所付出的自己财产的一部分,
以确保他所余财产的安全或快乐地享用这些财产
小区=国家,业主=公民,物业=政府;
你爱你的小区胜过你的生命吗?你愿意为了你们小区的富强奋斗你的毕生努力吗?
Netjob (离线)
积分
40380
帖子
960
发表于 2009-7-10 11:06:00 |显示全部楼层
路过~,顶一下。
500 字节以内
不支持自定义 Discuz! 代码
诸葛孔明 (离线)
积分
810369
帖子
1818
发表于 2009-7-10 12:26:13 |显示全部楼层
顶上,楼主辛苦
夫君子之行,静以修身,俭以养德,非淡泊无以明志,非宁静无以致远。
wangkj (离线)
积分
57305
帖子
3129
发表于 2009-7-10 15:19:32 |显示全部楼层
这个是俺搜出来的,写的最规范的。非原创。
qq:1248780
email:1248780@qq.com
VGA 显示卡 arm单片机 显卡 cortex-m0 fpga 烧写器 开发板

http://item.taobao.com/item.htm?id=7801503020
老郭 (离线)
积分
873173
帖子
5419
发表于 2009-7-10 21:55:02 |显示全部楼层
1.jpg
lelee007 (离线)
积分
29395
帖子
2683
发表于 2009-7-12 17:21:17 |显示全部楼层
顽强地路过,并顶之
jeff (离线)
积分
1
帖子
25
发表于 2010-7-2 17:55:03 |显示全部楼层
好咚咚
wangkj (离线)
积分
57305
帖子
3129
发表于 2010-7-2 19:14:09 |显示全部楼层
我靠,挖坟啊。
不过,这个问题,很多人多次问过。
qq:1248780
email:1248780@qq.com
VGA 显示卡 arm单片机 显卡 cortex-m0 fpga 烧写器 开发板

http://item.taobao.com/item.htm?id=7801503020
tkggwxfss (离线)
积分
345
帖子
13
发表于 2010-7-11 11:51:04 |显示全部楼层
谢谢啦
wangkj (离线)
积分
57305
帖子
3129
发表于 2010-7-12 09:30:19 |显示全部楼层
qq:1248780
email:1248780@qq.com
VGA 显示卡 arm单片机 显卡 cortex-m0 fpga 烧写器 开发板

http://item.taobao.com/item.htm?id=7801503020
kevin_chan (离线)
积分
56
帖子
4
发表于 2010-7-12 10:19:56 |显示全部楼层
谢谢,受用了
ksf1006 (离线)
积分
48
帖子
1
发表于 2010-7-20 14:42:38 |显示全部楼层
顶起来!!
solo_74 (离线)
积分
11469
帖子
209
发表于 2010-8-17 10:34:23 |显示全部楼层
看看,学习下!
wxw123321 (离线)
积分
719
帖子
58
发表于 2010-9-6 16:49:27 |显示全部楼层
顶起
fymbl (离线)
积分
52
帖子
409
发表于 2010-9-22 17:29:17 |显示全部楼层
学习一下。
lising (离线)
积分
9
帖子
429
发表于 2010-9-26 15:49:19 |显示全部楼层
不错!顶
marjolein (离线)
积分
2
帖子
43
发表于 2010-10-11 20:45:10 |显示全部楼层
thanks
dalfer (离线)
积分
966
帖子
30
发表于 2010-10-14 15:16:26 |显示全部楼层
模拟的SPI让我头疼,显示接口的SPI操作不关定时器中断就不行,不然会显示乱码,没办法!
您需要登录后才可以发表评论 登录 | 立即注册

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备11013910号 | 京公网安备11010502021702
回顶部