DS1302
定义引脚和引入头文件(ds1302.c)
#include "intrins.h"//官方底层用到了nop
sbit SDA = P2^3;//DS1302_IO
sbit RST = P1^3;//DS1302_CE
sbit SCK = P1^7;//DS1302_SCK
关键配置位说明(ds1302.c)
-
WP写保护位(地址0x8e)置1时,芯片禁止写入操作;置0时,才能进行时间配置
-
CH时钟停止位(地址为0x80-位于秒寄存器的最高位)置1时,停止时钟振荡器;置0时,启动时钟
时间参数写入流程(ds1302.c)
void Set_Rtc(unsigned char *ucRtc)
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);//关闭写保护
Write_Ds1302_Byte(0x80,0x80);//停止时钟振荡器
for(i=0;i<3;i++)//写入时间时,锁存器地址,秒-0x80,分-0x82,时-0x84
Write_Ds1302_Byte(0x84 - 2 * i,ucRtc[i] / 10 % 10 * 16 + ucRtc[i] % 10);//写入BCD数据。转换为十六进制
//BCD码转换公式十进制数值——高4位(十位)*16 + 低4位
Write_Ds1302_Byte(0x8e,0x80);//重新启用写保护
}
时间参数读取流程(ds1302.c)
void Read_Rtc(unsigned char *ucRtc)
{
unsigned char i;
unsigned temp;
EA = 0;//关闭全局中断保证事需完整性
for(i-0;i<3;i++)//读取时间时,锁存器地址,秒-0x81,分-0x83,时-0x85
{
temp = Read_Ds1302_Byte(0x85 - 2 * i);//读取地址自动递增
ucRtc[i] = temp / 16 * 10 + temp % 16;//BCD转十进制:高4位*10+低4位
}
EA = 1;//恢复中断
}
NE55(频率)
定时器0相关操作(main.c)
//定时器0,12MHz,16位(不自动重载),定时器时钟12T(千万不能开中断)
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
修改后(实现计数)
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置定时器模式 定时器0这边是0101,但不能影响定时器1
TL0 = 0x00; //设置定时初始值 TL0、TH0全用 0ms
TH0 = 0x00; //设置定时初始值 TL0、TH0全用 0ms
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
数据读取(main.c)
unsigned int time_all_1s;
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1;
}
void Timer1_Isr(void) interrupt 3
{
if(++time_all_1s == 1000)
{
time_all_1s = 0;
Freq = TH0 << 8 | TL0;//TH0取高8位
TH0 = TL0 = 0;//取完之后归0
}
}
注意事项
-
初始化顺序问题:必须先初始化定时器0,在初始化定时器1
-
第一次测量结果误差:让数码管1秒之后在显示,定义一个bit型变量,1秒之后bit置1,在显示
bit show_flag_first = 0; void Seg_Proc() { if(show_flag_first) { //进行频率显示 } } void Timer1_Isr(void) interrupt 3 { if(++time_all_1s == 1000) { show_flag_first = 1; time_all_1s = 0; Freq = TH0 << 8 | TL0;//TH0取高8位 TH0 = TL0 = 0;//取完之后归0 } } -
接线问题:跳线帽接P34和SIGNAL
-
按键问题:屏蔽P34
超声波
定义引脚(ultrasound.c)
sbit Tx = P1^0;//US_TX
sbit Rx = P1^1;//US_RX
换算
d = 0.017t(d的单位cm,t的单位us)
40kHz 一个周期1/40k=25us
延时函数(ultrasound.c)
//12us的延时函数
void Delay12us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
i = 3;
while (--i);
}
发送8个40kHz的方波(ultrasound.c)
void Ut_Wave_Init()
{
unsigned char i;
for(i=0;i<8;i++)
{
Tx = 1;
Delay12us();
Tx = 0;
Delay12us();
}
}
数据接收与转换(ultrasound.c)
unsigned char Ut_Wave_Data()
{
unsigned char time;
//选择定时器pca
CH = CL = 0;//类似于定时器0,TH0 = TL0 = 0;
CMOD = 0X00;//16位不自动重载计时器,类似于定时器 TMOD = 0x00;
EA = 0;
Ut_Wave_Init();
EA = 1;
CR = 1;//类似于定时器0 TR0 = 1;发送完成后,开始计时
while(Rx && !CF);//CF类似于定时器0 TF0;等待我们收到回应(收到回应后Rx=0)或者计数溢出(溢出后CF=1)
CR = 0;
if(!CF)
{
time = CH << 8 | CL;//时间读取
return (0.017 * time);
}
else//计数溢出
{
CF = 0;
return 0;
}
}
串口
串口初始化(Uart.c)
//串口1(通用)、12MHz、9600波特率、8位数据、定时器2(16位自动重载)、12T
//加上ES=1、EA=1开启串口中断和总中断
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xE6; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1;
EA = 1;
}
串口重定向(Uart.c)
#include "stdio.h"//引用头文件,调用putchar函数
extern char putchar(char ch)
{
SBUF = ch;
while(TI == 0);//发送成功后TI = 1;
TI = 0;
return ch;
}
//应用
unsigned char my_data = 5;
printf("%bu",my_data)
串口中断接收(main.c)
pdata unsigned char Uart_Buf[10] = 0;//串口接收缓冲区
idata unsigned char Uart_Rx_Index;//串口接收索引
idata unsigned char Uart_Recv_Tick;//串口接收时间标志
idata unsigned char Uart_Rx_Flag;
void Uart1_Isr(void) interrupt 4
{
//若接收到数据
if (RI) //检测串口1接收中断
{
Uart_Rx_Flag = 1; //接收标志
Uart_Recv_Tick = 0;//清零接收时间标志
Uart_Buf[Uart_Rx_Index++] = SBUF;//将数据保存到缓冲区
RI = 0; //清除串口1接收中断请求位
}
if(Uart_Rx_Index > 10)
{
Uart_Rx_Index = 0;//防止溢出
memset(Uart_Buf,0,10);
}
}
//定时器1
void Time1_Isr(void) interrupt 3
{
if(Uart_Rx_Flag)
Uart_Recv_Tick++;
}
串口处理函数(main.c)
void Uart_Proc()
{
if(Uart_Rx_Index == 0)
return;//无数据,直接驳回
if(Uart_Recv_Tick >= 10)//若接收超时,对数据读取,清空缓存区
{
Uart_Recv_Tick = 0;
Uart_Rx_Flag = 0;
//处理函数
meset(Uart_Buf,0,Uart_Rx_Index);//清空接收数据
Uart_Rx_Index = 0;
}
}
添加头文件(main.c)
#include "string.h"