原创 SPI接口的93c46程序

2008-4-9 10:07 7572 4 6 分类: MCU/ 嵌入式
去年做了个51的开发板,下面是用其中的93c46 eeprom的程序,c51写的。贴在这里充数。
/************************************
** FileName:at93c46.h
***********************************/
#ifndef __LZP_AT93C46_H_
#define __LZP_AT93C46_H_
#include "reg52.h"
#include "intrins.h"

//定义操作命令
#define READ     0xc0
#define WRITE    0xa0
#define ERASE    0xe0
#define EWEN     0x98
#define EWDS     0x80
#define WRAL     0x88
#define ERAL     0x90
 
sbit AT93C46_CS=P3^7;
sbit SPI_CLK=P1^4;
sbit SPI_DI=P1^3;
sbit SPI_DO=P1^2;

void clock(void);
void spi_send(unsigned char dat,unsigned char num);
unsigned char spi_receive(void);
void enable_write(void);
void disable_write(void);
unsigned char at93c46_read(unsigned char addr);
void at93c46_erase(unsigned char addr);
void at93c46_write(unsigned char addr,unsigned char dat);
void at93c46_writeall(unsigned char dat);
void at93c46_eraseall(void);
void init_spi_93c46(void);

#endif
/*********************************************
** FileName:at93c46.c
*********************************************/
#include "at93c46.h"

//#include "delay.h"

//产生一个时钟周期
void clock(void)
{
    SPI_CLK=0;
    _nop_();
    SPI_CLK=1;
    //_nop_();
}

//输入一个字节的数据到at93c46
void spi_send(unsigned char dat,unsigned char num)
{
    unsigned char i;
    for(i=0;i<num;i++)
    {
        SPI_DI=(bit)(dat&0x80);
        dat<<=1;
        clock();
    }
}

//从AT93C46接受一个字节的数据
unsigned char spi_receive(void)
{
    unsigned char i;
    unsigned char tmp=0;
    SPI_DO=1;
    while(SPI_DO)
        clock();
    for(i=0;i<8;i++)
    {
        clock();
        tmp<<=1;
        if(SPI_DO)
            tmp++;
    }
    clock();
    return tmp;
}

//读保存在at93c46存储器中地址为addr处的数据
unsigned char at93c46_read(unsigned char addr)
{
    unsigned char tmp;
//    enable_write();
    AT93C46_CS=0;
    addr<<=1;

    AT93C46_CS=1;
   
    spi_send(READ,3);
    spi_send(addr,7);
    tmp=spi_receive();
    AT93C46_CS=0;
//    disable_write();
    return tmp;
}

//使能写/删除操作
void enable_write(void)
{
    AT93C46_CS=0;
    SPI_CLK=0;
  
    AT93C46_CS=1;

    spi_send(EWEN,5);
    spi_send(0,5);
    AT93C46_CS=0;
}

//禁止写/删除操作
void disable_write(void)
{
    AT93C46_CS=0;
    SPI_CLK=0;

    AT93C46_CS=1;

    spi_send(EWDS,5);
    spi_send(0,5);
    AT93C46_CS=0;
}

//擦除地址为addr的存储单元
void at93c46_erase(unsigned char addr)
{
    enable_write();
    AT93C46_CS=0;
    SPI_DO=1;
    AT93C46_CS=1;
   
    addr<<=1;
    spi_send(ERASE,3);
    spi_send(addr,7);
    AT93C46_CS=0;
    AT93C46_CS=1;
    while(!SPI_DO)
        clock();
    AT93C46_CS=0;
    disable_write();
}

//往at93c46 addr地址写数据dat
void at93c46_write(unsigned char addr,unsigned char dat)
{
    _nop_();
    //檫除原先的数据
    at93c46_erase(addr);
    addr<<=1;
    enable_write();
    AT93C46_CS=1;
   
    spi_send(WRITE,3);
    spi_send(addr,7);
    spi_send(dat,8);
    AT93C46_CS=0;
    AT93C46_CS=1;
    while(!SPI_DO) clock();
    AT93C46_CS=0;
    disable_write();
}

//往at93c46所有存储单元写入dat
void at93c46_writeall(unsigned char dat)
{
    enable_write();
    _nop_();

    AT93C46_CS=1;

    spi_send(WRAL,5);
    spi_send(0,5);
    spi_send(dat,8);
    AT93C46_CS=0;
    AT93C46_CS=1;
    while(!SPI_DO) clock();
    AT93C46_CS=0;
    disable_write();
}

//擦除at93c46
void at93c46_eraseall(void)
{
    enable_write();
    _nop_();

    AT93C46_CS=1;
   
    spi_send(ERAL,5);
    spi_send(0,5);
    AT93C46_CS=0;
    AT93C46_CS=1;
    while(!SPI_DO) clock();
    AT93C46_CS=0;
    disable_write();
}

void init_spi_93c46(void)
{
    AT93C46_CS=0;
    SPI_DI=0;
    SPI_DO=1;
    SPI_CLK=0;
}



PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户377235 2014-6-14 17:13

你对spi的理解我不是很认同,上升沿写,下降沿读,你自己看看你的程序。

用户1671066 2013-9-23 19:46

正在需要时……

用户1621019 2013-6-6 14:25

分享精神可敬可佳

用户448261 2013-4-20 11:59

向您学习,还望您继续多分享一些宝贵的有利于初学者的资料,谢谢

用户1508872 2012-7-3 19:29

还不错。

用户1000871 2012-6-18 21:33

谢谢

用户201673 2009-1-15 14:52

向前辈学习
相关推荐阅读
用户1361860 2012-06-28 23:44
Nicrosystem Freescale Kinetis教程---SDHC
这是研究生翻译的SDHC的中文文档,里面很多句子不通,但我现在没时间去修改了。先放出来,应该还是会有一点作用  ...
用户1361860 2012-06-26 12:39
Nicrosystem Freescale Kinetis教程--低功耗定时器
Freescale Kinetis内部集成了一个独特的低功耗定时器,它可以在系统处于低功耗模式下,仍然以极低功耗运行,可以用于在适当时候唤醒系统进入正常工作模式  ...
用户1361860 2012-06-24 22:11
Nicrosystem Freescale Kinetis教程----RTC实时时钟
Nicrosystem的飞思卡尔kinetis教程之片上RTC  ...
用户1361860 2012-06-22 10:21
TI C2000微控制器指南
这是官方的C2000的介绍,C2000做电机控制那是业界最好的。  ...
用户1361860 2012-06-20 23:52
Nicrosystem Freescale Kinetis教程--PIT定时器教程
这是PIT定时器的教程,PIT是 Kinetis支持的另一种定时器,相对于上一讲的flextimer要简单。 今晚赶到北京,到宾馆发一篇博客  ...
用户1361860 2012-06-19 13:15
Nicrosystem Freescale Kinetis教程--Flextimer教程
Kinetis的Flextimer定时器教程 kinetis集成了众多功能各异的定时器,flextimer是其中最为复杂的一个  ...
EE直播间
更多
我要评论
2
4
关闭 站长推荐上一条 /3 下一条