⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex15.c

📁 C51单片机用C语言编写的SPI例程
💻 C
字号:
#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[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<len; i++)	readbuff[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);		// 装载显示缓冲
				}
			}	
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -