51单片机C语言编程实例2.docx

上传人:b****8 文档编号:10494301 上传时间:2023-02-14 格式:DOCX 页数:52 大小:29.09KB
下载 相关 举报
51单片机C语言编程实例2.docx_第1页
第1页 / 共52页
51单片机C语言编程实例2.docx_第2页
第2页 / 共52页
51单片机C语言编程实例2.docx_第3页
第3页 / 共52页
51单片机C语言编程实例2.docx_第4页
第4页 / 共52页
51单片机C语言编程实例2.docx_第5页
第5页 / 共52页
点击查看更多>>
下载资源
资源描述

51单片机C语言编程实例2.docx

《51单片机C语言编程实例2.docx》由会员分享,可在线阅读,更多相关《51单片机C语言编程实例2.docx(52页珍藏版)》请在冰豆网上搜索。

51单片机C语言编程实例2.docx

51单片机C语言编程实例2

【实例86】

总线接口的软件实现

/*引脚定义和相关头文件包含*/

#include

sbitI2C_SDA=P1^0;

sbitI2C_SCL=P1^1;

(1)函数voiddelay()

在C51中使用nop指令,实现一段时间的延时,程序代码如下:

voiddelay(void)

{

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

}

(2)函数voidi2c_start()

voidi2c_start(void)

{

I2C_SDA=1;

I2C_SCL=1;

delay();

I2C_SDA=0;

delay();

I2C_SCL=0;

}

(3)函数voidi2c_stop()

voidi2c_stop(void)

{

I2C_SDA=0;

I2C_SCL=1;

delay();

I2C_SDA=1;

delay();

I2C_SCL=0;

}

(4)函数voidi2c_ack()

voidi2c_ack(void)

{

I2C_SDA=0;

I2C_SCL=1;

delay();

I2C_SDA=1;

I2C_SCL=0;

}

(5)voidi2c_send_byte()

/*输入参数:

c*/

voidi2c_send_byte(unsignedcharc)

{

unsignedchari;

for(i=8;i>0;i--)

{

if(c&0x80)I2C_SDA=1;

elseI2C_SDA=0;

I2C_SCL=1;

delay();

I2C_SCL=0;

c=c<<1;

}

I2C_SDA=1;

/*释放数据线,准备接收应答信号*/

I2C_SCL=1;

delay();

while(!

(0==I2C_SDA

/*等待应答信号*/

&&1==I2C_SCL));

}

(6)函数unsignedchari2c_recv_byte()

/*输入参数:

c*/

/*返回数值:

从总线上读取的数据*/

unsignedchari2c_recv_byte(void)

{

unsignedchari;

unsignedcharr;

I2C_SDA=1;

for(i=8;i>0;i--)

{

r=r<<1;

/*左移补0*/

I2C_SCL=1;

delay();

if(I2C_SDA)r=r|0x01;

/*当数据线为高时,数据位为1*/

I2C_SCL=0;

}

returnr;

}

【实例87】SPI总线接口的软件实现

程序中端口宏定义如下:

#include

#include

#defineWREN0x06

/*设置写使能锁存器*/

#defineWRDI0x04

/*复位写使用锁存器*/

#defineRSDR0x05

/*读状态寄存器*/

#defineWRSR0x01

/*写状态寄存器(看门狗和块锁)*/

#defineREAD0x03

/*/读操作指令0000A8011*/

#defineWRITE0x02

/*写操作指令0000A8010*/

#defineWIP0x01

/*状态寄存器中写操作是否忙*/

/*各引脚定义*/

sbitX5045_SO=P1^1;

sbitX5045_SI=P1^6;

sbitX5045_SCK=P1^4;

sbitX5045_CS=P1^2;

(1)函数voidwrite_byte()

/*入口:

byte,要写入的8位数据*/

voidwrite_byte(unsignedcharbyte)

{

unsignedchari;

unsignedchartmp;

for(i=0;i<8;i++)

{

X5045_SCK=0;

tmp=byte&0x80;

if(tmp==0x80)

/*与0X80比较判断最高数据位是否为1*/

{

X5045_SI=1;

_nop_();

}

else

{

X5045_SI=0;

_nop_();

}

X5045_SCK=1;

byte=byte<<1;

}

}

(2)函数unsignedcharread_byte()

/*返回值:

从X5045中读取的8位数据*/

unsignedcharread_byte(void)

/*读数据,一次8位*/

{

unsignedchari;

unsignedcharbyte=0;

for(i=8;i>0;i--)

{

byte=byte<<1;

/*先读出的是高位*/

X5045_SCK=1;

_nop_();

_nop_();

X5045_SCK=0;

_nop_();

_nop_();

byte=byte|(unsignedchar)X5045_SO;

}

return(byte);

}

(3)函数voidx5045_start()和voidx5045_stop()

voidx5045_start(void)

{

X5045_CS=1;

_nop_();

_nop_();

X5045_SCK=0;

_nop_();

_nop_();

X5045_CS=0;

_nop_();

_nop_();

}

voidx5045_end(void)

{

X5045_SCK=0;

_nop_();

_nop_();

X5045_CS=1;

_nop_();

_nop_();

}

(4)函数unsignedcharx5045_read_status()

unsignedcharx5045_read_status(void)

{

unsignedchartmp;

x5045_start();

write_byte(RSDR);

tmp=read_byte();

x5045_end();

returntmp;

}

(5)函数voidx5045_write_status()

voidx5045_write_status(unsignedcharstatus)

{

unsignedchartmp;

/*写操作之前先使能写操作*/

x5045_start();

write_byte(WREN);

x5045_end();

/*写入状态寄存器*/

x5045_start();

write_byte(WRSR);

write_byte(status);

x5045_end();

/*检查写操作是否完成*/

do

{

x5045_start();

write_byte(RSDR);

/*RSDRreadstatusregesiter*/

tmp=read_byte();

x5045_end();

}

while(tmp&WIP);

}

(6)函数unsignedcharread_addr_data()

/*函数入口:

addr,要读取数据的地址*/

unsignedcharread_addr_data(unsignedintaddr)

{

unsignedcharaddr_tmp,tmp;

unsignedcharread_cmd;

if(addr>255)read_cmd=READ|0X08;

/*如果超出了一页,则名字字节A8为1*/

elseread_cmd=READ;

addr_tmp=(unsignedchar)(addr&0xff);

x5045_start();

write_byte(read_cmd);

write_byte(addr_tmp);

tmp=read_byte();

x5045_end();

returntmp;

}

(7)函数voidwrite_addr_data()

/*入口地址:

addr,要写入数据的地址*/

voidwrite_addr_data(unsignedintaddr,unsignedcharedata)

{

unsignedchartmp,addr_tmp;

unsignedcharcmd_tmp;

/*写使能操作*/

x5045_start();

write_byte(WREN);

x5045_end();

/*地址和写操作指令调节*/

if(addr>255)cmd_tmp=WRITE|0x08;

elsecmd_tmp=WRITE;

addr_tmp=(unsignedchar)(addr&0xff);

/*向指定地址写入数据*/

x5045_start();

write_byte(cmd_tmp);

write_byte(addr_tmp);

write_byte(edata);

x5045_end();

/*检查写操作是否完成*/

do

{

x5045_start();

write_byte(RSDR);

tmp=read_byte();

x5045_end();

}

while(tmp&WIP);

}

(8)函数voidreset_wdt()

voidreset_wdt(void)

{

X5045_CS=0;

_nop_();

_nop_();

X5045_CS=1;

nop_();

_nop_();

}

【实例88】1-WIRE总线接口的软件实现

(1)函数void_1wire_init()

/*包含头文件*/

#include

#include

/*引脚定义*/

sbitDQ=P1^2;

/*函数名称:

单总线初始化*/

voidinit(void)

{

unsignedchari;

DQ=1;

DQ=0;

for(i=200;i>0;i--)_nop_();

/*延时约600μs*/

DQ=1;

for(i=10;i>0;i--)_nop_();

/*延时约30μs*/

while(DQ==1);

for(i=100;i>0;i--)_nop_();

/*延时约300μs*/

DQ=1;

}

(2)函数voidwrite_bit_1()

voidwrite_bit_1(void)

{

unsignedchari;

DQ=1;

DQ=0;

for(i=25;i>0;i--)_nop_();

/*延时约90μs*/

DQ=1;

}

(3)函数voidwrite_bit_0()

voidwrite_bit_0(void)

{

unsignedchari;

DQ=1;

DQ=0;

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

DQ=1;

for(i=25;i>0;i--)_nop_();

/*延时约90μs*/

}

(4)另外仔细观察1-WIRE总线的写时序图,可将写“1”和写“0”合为一个函数。

voidwrite_bit(bitD)

{

unsignedchari;

DQ=1;

DQ=0;

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

DQ=D

for(i=25;i>0;i--)_nop_();

/*延时约90us*/

DQ=1;

}

(5)函数bitread_bit()

bitread_bit(void)

{

unsignedchari;

DQ=0;

for(i=0;i<5;i++)_nop_();

if(DQ==1)

{

return1;

}

else

{

return0;

}

}

(6)函数voidwrite_byte()

voidwrite_byte(unsigendcharbyte)

{

unsignedchari;

unsignedchartmp;

tmp=byte&0x01

for(i=0;i<8;i++)

{

tmp=byte>>i;

/*将要写的数据字节右移i位*/

tmp&=0x01;

/*得到数据字节的第i位*/

write_bit((bit)tmp);

}

}

(7)函数unsignedcharread_byte()

unsignedcharread_byte(void)

{

unsignedchari;

unsignedchartmp;

.

tmp=0;

/*将返回值初始化为0*/

for(i=0;i<8;i++)

{

if(read_bit())

/*如果当前读取的数据位为1*/

{

tmp=tmp|(0x01<

/*将返回字节对应的数据位置为1*/

}

}

for(i=0;i<20;i++)_nop_();

/*等待时序结束*/

}

【实例89】单片机外挂CAN总线接口

SJA1000_Config_Normal()

{

BTR0=0x00;

BTR1=0x14;

/*设置为1M波特率通信*/

SJAEntryResetMode();

/*进入复位模式*/

WriteSJAReg(REG_CAN_CDR,0xc8);

/*配置时钟分频寄存器,选择PeliCAN模式*/

WriteSJAReg(REG_CAN_MOD,0x05);

/*配置模式寄存器,选择双滤波、自发自收模式*/

WriteSJARegBlock(16,Send_CAN_Filter,8);

/*配置验收代码/屏蔽寄存器*/

WriteSJAReg(REG_CAN_BTR0,BTR0);

/*配置总线定时器0x00*/

WriteSJAReg(REG_CAN_BTR1,BTR1);

/*配置总线定时器0x14*/

WriteSJAReg(REG_CAN_OCR,0x1a);

/*配置输出管脚,推挽输出。

*/

SJAQuitResetMode();

/*退出复位模式,进入工作模式*/

}

报文发送程序如下所示:

/*==============================================================*/

/*函数原型:

bitBCAN_DATA_WRITE(unsignedchar*SendDataBuf)*/

/*参数说明:

特定帧各式的数据*/

/*返回值:

*/

/*0;表示将数据成功的送至发送缓冲区*/

/*1;表示上一次的数据正在发送,*/

/*说明:

将待发送特定帧各式的数据,送入SJA1000发送缓存区中,然后启动*/

/*SJA1000发送。

*/

/*特定帧格式为:

开始的两个字节存放'描述符',以后的为数据*/

/*描述符包括11位长的ID(标志符)\1位RTR\4位描述数据长度的DLC共16位*/

/*注:

本函数的返回值仅指示,将数据正确写入SJA1000发送缓存区中与否。

*/

/*不指示SJA1000将该数据正确发送到CAN总线上完毕与否*/

/*================================================================*/

bitBCAN_DATA_WRITE(unsignedchar*SendDataBuf)

{

unsignedcharTempCount;

SJA_BCANAdr=REG_STATUS;

/*访问地址指向状态寄存器*/

if((*SJA_BCANAdr&0x08)==0)

/*判断上次发送是否完成*/

{

return1;

}

if((*SJA_BCANAdr&0x04)==0)

/*判断发送缓冲区是否锁定*/

{

return1;

}

SJA_BCANAdr=REG_TxBuffer1;

/*访问地址指向发送缓冲区1*/

if((SendDataBuf[1]&0x10)==0)

/*判断RTR,从而得出是数据帧还是远程帧*/

{

TempCount=(SendDataBuf[1]&0x0f)+2;

/*输入数据帧*/

}

else

{

TempCount=2;

/*远程帧*/

}

memcpy(SJA_BCANAdr,SendDataBuf,TempCount);

return0;

}

报文接收程序如下所示:

/*==============================================================*/

/*函数原型:

bitBCAN_DATA_WRITE(unsignedchar*SendDataBuf)*/

/*参数说明:

特定帧各式的数据*/

/*返回值:

*/

/*0;表示将数据成功的送至发送缓冲区*/

/*1;表示上一次的数据正在发送,*/

/*说明:

将待发送特定帧各式的数据,送入SJA1000发送缓存区中,然后启动*/

/*SJA1000发送。

*/

/*特定帧格式为:

开始的两个字节存放'描述符',以后的为数据*/

/*描述符包括11位长的ID(标志符)\1位RTR\4位描述数据长度的DLC共16位*/

/*注:

本函数的返回值仅指示,将数据正确写入SJA1000发送缓存区中与否。

*/

/*不指示SJA1000将该数据正确发送到CAN总线上完毕与否*/

/*================================================================*/

bitBCAN_DATA_WRITE(unsignedchar*SendDataBuf)

{

unsignedcharTempCount;

SJA_BCANAdr=REG_STATUS;

/*访问地址指向状态寄存器*/

if((*SJA_BCANAdr&0x08)==0)

/*判断上次发送是否完成*/

{

return1;

}

if((*SJA_BCANAdr&0x04)==0)

/*判断发送缓冲区是否锁定*/

{

return1;

}

SJA_BCANAdr=REG_TxBuffer1;

/*访问地址指向发送缓冲区1*/

if((SendDataBuf[1]&0x10)==0)

/*判断RTR,从而得出是数据帧还是远程帧*/

{

TempCount=(SendDataBuf[1]&0x0f)+2;

/*输入数据帧*/

}

else

{

TempCount=2;

/*远程帧*/

}

memcpy(SJA_BCANAdr,SendDataBuf,TempCount);

return0;

}

【实例90】单片机外挂USB总线接口

unsignedcharcodeDeviceDescriptor[]=

{

18,/*bLength,长度(18字节)*/

1,/*bDescriptorType,描述符类型,1代表设备描述符*/

0x10,1,/*bcdUSB,USB规范版本1.1,以BCD码表示*/

0,/*bDeviceClass,设备类码*/

0,/*bDeviceSubClass,设备子类码*/

1,/*bDeviceProtocol,设备协议*/

16,/*bMaxPacketSize0,最大封包大小*/

0xff,0xff,/*idVendor,制造商ID,每个厂商有不同的ID,这里未定义*/

0,1,/*idProduct,产品ID,每个厂商为自己生产的不同产品定义*/

0,0,/*bcdDevice,发行序号,以BCD码表示*/

1,/*iManufacturer,制造商的字符串描述符索引*/

2,/*iProduct,产品的字符串描述符索引*/

0,/*iSerialNumber,设备序号的字符串描述符索引*/

1,/*bNumConfigurations,配置描述符的个数*/

};

CH375初始化程序如下:

#defineCH375HM_INT_ENEX0

/*单片机的INT0引脚的中断使能*/

#defineCH375HM_INT_FLAGIE0

/*单片机的INT0引脚的中断标志*/

/*其他程序代码*/

/*假定CH375模块的INT#引脚连接到单片机的INT0引脚*/

IT0=1;

/*置CH375模块中断信号为下降沿触发,实际上,电平触发方式也可以*/

CH375HM_INT_FLAG=0;

/*清中断标志*/

CH375HM_INT_EN=1;

/*允许CH375模块中断*/

CH375提供的开放的命令库函数如下:

#defineCH375HM_INDEX_WR(Index)

{

CH375HM_INDEX=(Index);

}

/*写索引地址*/

#defineCH375HM_DATA_WR(Data)

{

CH375HM_DATA=(Data);

}

/*写数据*/

#defineCH375HM_DATA_RD()(CH375HM_DATA)

/*读数据*/

/*其他程序代码*/

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > IT认证

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1