81【看懂网站代码结构】

我们随便找到打开一个网页,鼠标右键查看源码,我们首先是看body部分,这是组件
组件的写法如:
<b>内容</b>        文字加粗
<h1>内容</h1>    使用h1号字体显示文字
我们现在来升华一下,组件是可以携带属性的
<h1 class="c1">内容</h1>,这种写法便是附加参数大概来讲,就是可以对该组件进行一定的属性规定


重点:并不是所有组件(标签)都有结束符号,我们现在来创建一个文本输入框

01
02
03
04
05
06
07
08
09
10
11
12
13
<!DOCTYPE html>
<html>
<head>
        <title>第2个程序</title>
 
 
</head>
<body>
 
        <input type="" name="" placeholder="请输入账号">
 
</body>
</html>




<input>就是创建文本输入框的代码,placeholder="请输入账号"是属性规定,文本框里会有提示文本,运行结果如下:





<title>第2个程序</title>这个是设置标题的代码,在head里面

<think> 我们之前讨论过DS1302的驱动代码问题,现在用户要求详细解释初始化、写入字节、读取字节三个函数的工作原理。结合用户提供的代码和之前的分析,我将详细解释每个函数的工作原理,并指出之前发现的问题及修正方法。 ### 1. DS1302_Init 初始化函数 ```c void DS1302_Init(void) { DS1302_CE = 0; // CE引脚置低,禁用芯片 DS1302_SCLK = 0; // 时钟线置低 } ``` **工作原理**: - 该函数在系统启动时调用,用于初始化DS1302的通信引脚状态。 - 将CE(也称为RST)引脚置0,确保芯片处于非活动状态。 - 将SCLK(时钟线)置0,为后续通信提供初始状态。 **问题与改进**: - 此初始化仅设置引脚状态,并未配置DS1302内部寄存器。实际使用中,通常需要关闭写保护并设置初始时间。 - 改进建议:在初始化后关闭写保护寄存器(地址0x8E),以允许写入时间数据: ```c void DS1302_Init(void) { DS1302_CE = 0; DS1302_SCLK = 0; // 关闭写保护 DS1302_WriteByte(0x8E, 0x00); // 0x8E是写保护寄存器地址,0x00表示关闭写保护 } ``` ### 2. DS1302_WriteByte 写入字节函数 ```c void DS1302_WriteByte(unsigned char Command, unsigned char Data) { unsigned char i; DS1302_CE = 1; // 使能芯片(CE置高) // 写入8位命令(地址/控制字) for (i = 0; i < 8; i++) { DS1302_IO = Command & (0x01 << i); // 依次取出Command的每一位(从最低位开始) DS1302_SCLK = 1; // 上升沿写入数据 DS1302_SCLK = 0; // 时钟拉低,准备下一次写入 } // 写入8位数据 for (i = 0; i < 8; i++) { DS1302_IO = Data & (0x01 << i); // 依次取出Data的每一位 DS1302_SCLK = 1; DS1302_SCLK = 0; } DS1302_CE = 0; // 禁用芯片 } ``` **工作原理**: 1. 拉高CE引脚,启动数据传输。 2. **命令写入阶段**:循环8次,每次将Command的当前位(从LSB开始)输出到IO线,然后产生一个时钟上升沿(SCLK从0到1),DS1302在上升沿采样数据。 3. **数据写入阶段**:同样循环8次,将Data的每一位依次写入。 4. 完成后拉低CE,结束传输。 **时序关键点**: - 写操作时,数据在SCLK上升沿被DS1302锁存。 - 命令字节的格式:最高位(MSB)固定为1,第6位为1表示时钟/日历数据,最低位(LSB)为0表示写操作。例如,写入秒寄存器的命令为0x80(10000000)[^1]。 **问题与改进**: - 原代码未考虑IO方向设置(需配置为输出模式),但在51单片机中IO默认为准双向口,通常可工作。 - 缺少延时:高速单片机需在SCLK跳变后增加短暂延时(如`delay_us(2)`)确保信号稳定。 ### 3. DS1302_ReadByte 读取字节函数 ```c unsigned char DS1302_ReadByte(unsigned char Command) { unsigned char i, Data = 0x00; Command |= 0x01; // 将命令的LSB置1(表示读操作) DS1302_CE = 1; // 使能芯片 // 写入8位命令(读操作) for (i = 0; i < 8; i++) { DS1302_IO = Command & (0x01 << i); // 输出命令的每一位 DS1302_SCLK = 0; // 先拉低时钟 DS1302_SCLK = 1; // 再拉高,产生上升沿(写入命令) } // 读取8位数据 for (i = 0; i < 8; i++) { DS1302_SCLK = 1; // 先拉高 DS1302_SCLK = 0; // 再拉低,产生下降沿(DS1302在下降沿后输出下一位数据) if (DS1302_IO) { Data |= (0x01 << i); // 读取当前位(从LSB开始) } } DS1302_CE = 0; // 禁用芯片 DS1302_IO = 0; // 释放IO线 return Data; } ``` **工作原理**: 1. 拉高CE引脚启动传输。 2. **命令写入阶段**:将读命令(Command | 0x01)写入DS1302(与写函数相同)。 3. **数据读取阶段**: - 循环8次,每次先拉高SCLK(此时DS1302准备数据),再拉低SCLK(下降沿后DS1302将下一位数据输出到IO)。 - 在SCLK为低电平时读取IO状态,并保存到Data变量。 4. 拉低CE结束传输。 **时序关键点**: - 读操作时,DS1302在SCLK下降沿后更新IO线上的数据。因此,应在SCLK拉低后读取IO[^2]。 - 命令字节的LSB必须为1(读操作),例如读秒寄存器的命令为0x81(10000001)。 **原代码问题与修正**: - 原用户代码存在严重时序错误: ```c // 原错误代码片段: for(i=0;i<8;i++) { DS1302_SCLK=1; DS1302_SCLK=0; if(DS1302_IO){Data|=(0x01<<i);} // 在下降沿后读取,但顺序错误 } ``` 问题:在SCLK从1到0(下降沿)后立即读取是正确的,但循环中先产生下降沿再读取,逻辑正确但实现有误。实际原代码中,在下降沿后读取,但循环结构可能导致时序不匹配。 - **脉冲数量错误**:DS1302读操作共需15个SCLK脉冲(8命令+7数据?)。实际上,标准DS1302读操作需8个命令脉冲+8个数据脉冲,共16个脉冲[^4]。但原代码问题在于读取循环内的SCLK操作顺序。 - **修正重点**:确保在SCLK下降沿之后读取数据,且读取循环内先产生下降沿再采样。原代码结构正确,但需确认IO方向(读取前应设置为输入模式)。 ### 总结:完整工作流程 1. **初始化**:关闭写保护,设置初始时间(可选)。 2. **写入时间**:使用`DS1302_WriteByte`写入各时间寄存器(注意BCD码转换)。 3. **读取时间**:使用`DS1302_ReadByte`读取寄存器,并将返回的BCD码转换为十进制显示。 ### 示例:设置和读取秒寄存器 ```c // 设置秒数为30(BCD码0x30) DS1302_WriteByte(0x80, 0x30); // 0x80为秒寄存器写命令 // 读取秒数 unsigned char second = DS1302_ReadByte(0x81); // 0x81为秒寄存器读命令 second = (second >> 4) * 10 + (second & 0x0F); // BCD转十进制 ``` ### 注意事项 1. **BCD码转换**:DS1302使用BCD码存储时间,读取后需转换。 2. **写保护**:每次写入前确保写保护关闭(寄存器0x8E=0x00)。 3. **时钟停止位**:秒寄存器(地址0x80)的最高位为时钟停止位(1停止,0启动),初始化时需清零。 --- §§相关问题§§ 1. DS1302的时钟停止位如何影响计时功能? 2. 如何验证DS1302的读写时序是否正确? 3. 除了时间寄存器,DS1302的RAM如何读写? 4. DS1302的涓流充电功能如何配置? </think>### DS1302驱动代码详细解析 #### 1. `DS1302_Init` 初始化函数 ```c void DS1302_Init(void) { DS1302_CE = 0; // 禁用芯片(CE/RST置低) DS1302_SCLK = 0; // 时钟线置低 } ``` **工作原理**: 1. **CE/RST引脚控制**: - 当CE=0时,DS1302进入待机状态,停止所有数据传输 - 确保初始化时芯片处于非活动状态 2. **SCLK初始化**: - 时钟线保持低电平,为后续通信提供稳定起点 - 符合DS1302时序要求:SCLK在空闲状态必须为低电平[^1] **关键点**: - 此函数仅完成引脚初始化,实际使用中需补充写保护关闭操作: ```c // 应在初始化后添加 DS1302_WriteByte(0x8E, 0x00); // 关闭写保护(地址0x8E) ``` --- #### 2. `DS1302_WriteByte` 写入函数 ```c void DS1302_WriteByte(unsigned char Command, unsigned char Data) { unsigned char i; DS1302_CE = 1; // 激活芯片(CE置高) // 写入命令字节(8位) for(i=0; i<8; i++) { DS1302_IO = Command & (0x01 << i); // 取出第i位 DS1302_SCLK = 1; // 上升沿锁存数据 DS1302_SCLK = 0; // 准备下一位 } // 写入数据字节(8位) for(i=0; i<8; i++) { DS1302_IO = Data & (0x01 << i); DS1302_SCLK = 1; DS1302_SCLK = 0; } DS1302_CE = 0; // 结束传输 } ``` **时序解析**: 1. **启动传输**: - 置CE=1激活芯片(最小脉宽需$t_{CC}=4\mu s$) 2. **命令写入阶段**: - 循环8次,每次传输1位(LSB优先) - SCLK上升沿时DS1302采样IO数据 - 命令格式:$D7$(1=突发模式),$D6-D1$(地址),$D0$(0=写操作) 3. **数据写入阶段**: - 相同方式写入8位数据 - 数据格式为BCD码(如$0x59$表示59秒) 4. **结束传输**: - 置CE=0终止通信(最小脉宽$t_{CWH}=4\mu s$) **时序图示例**: ``` CE: ______|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|______ SCLK: __|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|__ IO: __D0_D1_D2_D3_D4_D5_D6_D7__ (命令) __D0_D1_D2_D3_D4_D5_D6_D7__ (数据) ``` *注:D0为最低位,首先传输* --- #### 3. `DS1302_ReadByte` 读取函数(含修正) ```c unsigned char DS1302_ReadByte(unsigned char Command) { unsigned char i, Data = 0x00; Command |= 0x01; // 设置读操作位(D0=1) DS1302_CE = 1; // 激活芯片 // 写入读命令(8位) for(i=0; i<8; i++) { DS1302_IO = Command & (0x01 << i); DS1302_SCLK = 0; // 先拉低 DS1302_SCLK = 1; // 上升沿写入 } // 正确读取时序(修正后) for(i=0; i<8; i++) { DS1302_SCLK = 1; // 1. 上升沿(DS1302准备下一位) DS1302_SCLK = 0; // 2. 下降沿(DS1302输出数据) if(DS1302_IO) { Data |= (0x01 << i); // 3. 读取当前位 } } DS1302_CE = 0; // 禁用芯片 DS1302_IO = 0; // 释放IO线 return Data; } ``` **关键修正点**: 1. **读取时序修正**: - 原错误:在SCLK下降沿前读取数据 - 修正后:**下降沿后**读取(DS1302在下降沿更新IO输出) 2. **脉冲数量控制**: - 总脉冲数 = 8(命令)+ 8(数据) = 16个脉冲 - 符合DS1302要求:每个字节传输需要8个时钟脉冲[^4] 3. **命令字处理**: - `Command |= 0x01`:确保D0=1(读操作) - 例如读秒寄存器:0x80 → 0x81 **数据读取原理**: 1. DS1302在SCLK下降沿后更新IO引脚状态 2. 单片机在SCLK低电平期间采样IO状态 3. 数据位顺序:LSB(D0)先传输,MSB(D7)最后 --- ### 典型问题解决方案 1. **显示255问题**: - 原因:未关闭写保护/读取时序错误 - 解决: ```c // 初始化时关闭写保护 DS1302_WriteByte(0x8E, 0x00); // 使用修正的读取函数 second = DS1302_ReadByte(0x81); ``` 2. **BCD码转换**: ```c // BCD转十进制函数 uchar bcd_to_dec(uchar bcd) { return (bcd >> 4) * 10 + (bcd & 0x0F); } // 使用示例 uchar sec = bcd_to_dec(DS1302_ReadByte(0x81)); ``` 3. **时间设置**: ```c // 设置12时30分45秒(BCD格式) DS1302_WriteByte(0x8E, 0x00); // 关写保护 DS1302_WriteByte(0x84, 0x12); // 小时 DS1302_WriteByte(0x82, 0x30); // 分钟 DS1302_WriteByte(0x80, 0x45); // 秒(D7=0启动时钟) ``` --- ### 工作流程总结 ```mermaid graph TD A[初始化] --> B[关闭写保护] B --> C[设置时间] C --> D[循环读取] D --> E[BCD转十进制] E --> F[LCD显示] ``` 1. **初始化序列**:CE=0, SCLK=0 2. **写操作序列**:CE↑ → 写命令 → 写数据 → CE↓ 3. **读操作序列**:CE↑ → 写命令 → 读数据 → CE↓ 4. **数据格式**:所有时间数据均使用BCD编码 > 完整代码实现参考DS1302数据手册时序图[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学编程的闹钟

自愿打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值