目录
复习使用,代码根据网上资料修改,仅供参考
ds1302
原理图
手册
ds1302.c
main.c
onewire
原理图
手册
onewire.c
main.c
IIC
PCF8591
原理图
手册
iic.c
main.c
AT2402
原理图
手册
main.c
串口UART
uart.c
main.c
发送数据
中断接收数据
超声波
ult.c
main.c
N555频率输出
main.c
PWM控制LED
复习使用,代码根据网上资料修改,仅供参考
———————————————————————————————————————————
ds1302
原理图
手册
注册地址/定义
需要注意0x8E,0x00开始写入
0x8F,0x80开始读出时间
ds1302.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "ds1302.h"
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
通过for循环依此写入,根据需要可自行修改
0x84 0x82 0x80写入地址
//将数组time中的值写到DS1302
void Time_Write(u8 * time)//写时间
{
Write_Ds1302_Byte(0x8e,0x00);//关闭写保护
Write_Ds1302_Byte(0x84,ucRtc[0] | 0x80);
Write_Ds1302_Byte(0x82,ucRtc[1]);
Write_Ds1302_Byte(0x80,ucRtc[2]);//在0x84 0x82 0x80地址中写入
Write_Ds1302_Byte(0x8e,0x80);//开启写保护
}
0x85 0x83 0x81读取地址
//读出DS1302中的时间
void Time_Read(u8 * time)//读时间
{
u8 i;
i = Read_Ds1302_Byte(0x85);
i = i << 1;
i = i >> 1;
ucRtc[0] = i;
ucRtc[1] = Read_Ds1302_Byte(0x83);
ucRtc[2] = Read_Ds1302_Byte(0x81);//在0x85 0x83 0x81地址中读出时间
}
main.c
写时间
u8 time[3] = {0x23,0x59,0x50};//时、分、秒
void main()
{
Time_Write(time);//主函数中调用写函数
while(1)
{
}
}
读时间
void seg_pro()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
//读时间
Time_Read(time);
//数码管显示
Seg_Buf[0] = time[0] / 16;//时
Seg_Buf[1] = time[0] % 16;
Seg_Buf[2] = 17;
Seg_Buf[3] = time[1] / 16;//分
Seg_Buf[4] = time[1] % 16;
Seg_Buf[5] = 17;
Seg_Buf[6] = time[2] / 16;//秒
Seg_Buf[7] = time[2] % 16;
}
注意是要除以16
onewire
原理图
手册
不想看直接跳过,在背下面
跳过ROM
转换T
读取刮板
太多了,直接看手册11页,或者记住0xcc 0x44 0xcc 0xbe
onewire.c
#include <STC15F2K60S2.H>
#include "onewire.h"
sbit DQ = P1^4;
总共调用3个函数——直接背
注意我这*6.25,出去直接是4位,省去转换float
u16 Temp_Read(void)
{
u8 low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
return ((high << 8) | low) * 6.25;
}
一定要注意这里先读低位再读高位!!!
main.c
加入这个while跳过上电85度
void main()
{
while(Temp_Read()/100 == 85);//当温度等于85度时进入while循环,不等于时跳出
while(1)
{
}
}
数码管显示
u16 Temperature;//实时温度变量
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
Temperature = Temp_Read();//实时读取温度值
Seg_Point[5] = 1;//加入小数点
Seg_Buf[4] = Temperature / 1000;
Seg_Buf[5] = Temperature % 1000 /100;
Seg_Buf[6] = Temperature % 100 / 10;
Seg_Buf[7] = Temperature % 10;
}
IIC
PCF8591
原理图
01——chanel 1——AIN1 03——chanel 3——AIN3
光敏电阻0x01 电位器0x03
手册
总线协议的读取模式,AD转换
总线协议的写入模式,D/A转换
地址字节
低电平读 0x90、高电平写 0x91
控制字节
模拟输出启用标志:如果为1,则模拟输出激活(DA输出时需注意)
iic.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "iic.h"
#define DELAY_TIME 5
sbit sda = P2^1;
sbit scl = P2^0;
AD转换
u8 Pcf8591_AD(u8 addr)//将addr地址中电压读出
{
u8 dat;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return dat;
}
DA转换
void Pcf8591_DA(u8 dat,addr)//将电压值dat输入到地址addr中
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
main.c
u16 AD;
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
AD = (Pcf8591_AD(0x03) * 100) / 51;//将电位器幅值传递到AD
Pcf8591_DA((5 * 51),0x41);//将5V电压输入到光敏电阻,记得开启模拟输出
Seg_Point[5] = 1;
Seg_Buf[5] = AD / 100;
Seg_Buf[6] = AD % 100 /10;
Seg_Buf[7] = AD % 10;
}
模拟输出可用万用表测量 红表笔接D/A 黑表笔接GND
AT2402
原理图
A2 A1 A0都接地,为0
手册
设备地址
0xa0写 0xa1读
iic.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "iic.h"
#define DELAY_TIME 5
sbit sda = P2^1;
sbit scl = P2^0;
在addr地址中读出存储值
u8 EEPROM_Read(u8 addr)
{
u8 temp;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
temp = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return temp;
}
将需要存储的值写入地址addr中
void EEPROM_Write(u8 dat,addr)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
I2C_Delay(1000);
}
注意这里连续写需要加延时,延时时长可自行修改,大概5ms以上!!!
与AD转换类似,只是地址不一样,背一个可以用两个
串口UART
uart.c
#include <STC15F2K60S2.H>
#include "uart.h"
波特率设置
void UartInit() //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xC7; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1;
EA = 1;
}
注意 ES = 1;
EA = 1;
void sendstring(u8 * dat)
{
while(*dat != '\0')
{
SBUF = *dat;
while(TI == 0);//等待数据发送
TI = 0;
dat++;
}
}
记得添加到主函数while前面进行初始化
void main()
{
UartInit();//初始化串口中断
while(1)
{
}
}
用stc软件可生成:
main.c
发送数据
使用sprintf需调用此头文件 #include "stdio.h"
#include "stdio.h"
u8 uart_dat[15];//存储数据
void main()
{
UartInit();
sprintf(uart_dat,"Distance:%d\r\n",(u16)wave_dat);//将需要发送数据存储到uart_dat中
sendstring(uart_dat);//发送uart_dat中的数据
}
%d为十进制,注意将需要显示的数据转为十进制
sprintf函数将数据写入uart_dat中,再通过sendstring()发送数据,发送数据按要求可以放在需要发送的位置
中断接收数据
u8 uart_slow;//数据发送减速
u8 uart_dat[15];//存储数据
u8 uart_rev[7];//接收数据
u8 uart_num;//收发数据长度
void uart_pro()
{
if(uart_slow) return;
uart_slow = 1;
if(uart_num == 6)
{
if(strcmp(uart_rev,"Return")==0)//比较函数需在头文件加#include "string.h"
{
sprintf(uart_dat,"Noises:%.1fdB\r\n",(float)noise/10.0);
send_string(uart_dat);
}
uart_num = 0;
}
}
void uart1() interrupt 4
{
if(RI == 1)
{
uart_rev[uart_num] = SBUF;
uart_num++;
RI = 0;
}
}
void main()
{
while(1)
{
uart_pro();
}
}
通过判断中断是否溢出来获取数据,每溢出一次就获取一个字节,并把每次获取存入数组中
将收到的数据进行比较,执行下一步操作,注意收到数据为ANSI码值十进制,0对应为48,所以需要减去48。
这里是将收到数据进行比较,当收到Return时,发送一个数据(按要求可以自行修改需要发送的数据)
超声波
跳线帽1-3 2-4超声波
ult.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "ult.h"
sbit tx = P1^0;
sbit rx = P1^1;
void Delay15us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 42;
while (--i);
}
void wave_init()//初始化超声波函数,发送8个波
{
u8 i;
for(i = 0;i < 8;i++)
{
tx = 1;
Delay15us();
tx = 0;
Delay15us();
}
}
u8 wave_read()//返回读出距离
{
u16 time;
TMOD &= 0xf0;
TH0 = TL0 = 0;
wave_init();
TR0 = 1;
while((rx == 1) && (TF0 == 0));
TR0 = 0;
if(TF0 == 0)
{
time = TH0 << 8 | TL0;
return (time * 0.017);
}
else
{
TF0 = 0;
return 0;
}
}
通过发送并接收8次波进行测量:
1、通过TX引脚发送并接收8次波
2、启动定时器,计算计数脉冲
3、等待超声波返回,接收到信号后,RX引脚变为低电平
4、关闭定时器,读取脉冲个数
距离l = (340m/s*t)/2
直接记住将时间t(即计数脉冲个数)*0.017
延时函数可用stc软件生成
我这里延时15us,测出来数据要准确,可自行修改测试
main.c
读出距离并显示出来
u8 wave_dat;
void seg_pro()
{
if(seg_slow) return;
seg_slow = 1;
wave_dat = wave_read();
seg_dat[5] = wave_dat / 100;
seg_dat[6] = wave_dat % 100 / 10;
seg_dat[7] = wave_dat % 10;
}
N555频率输出
main.c
定时器0设置1ms来完成计数功能
函数中需加入TMOD |= 0x05;
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置计数模式
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
定时器1设置1ms来完成定时功能
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //定时器中断1打开
EA = 1; //总中断打开
}
中断计数、数码管显示
u16 freq;
u16 count_f;
void Timer0Server() interrupt 3
{
if(++count_f == 1000)
{
count_f = 0;
freq = TH0 << 8 | TL0;
TH0 = TL0 = 0;
}
}
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
Seg_Buf[3] = freq / 10000;
Seg_Buf[4] = freq % 10000 / 1000;
Seg_Buf[5] = freq % 1000 / 100;
Seg_Buf[6] = freq % 100 / 10;
Seg_Buf[7] = freq % 10;
while(Seg_Buf[i] == 0)//这里让数据前面如果为0则不显示
{
Seg_Buf[i] = 16;
if(++i == 7) break;
}
}
亲测有效
PWM控制LED
#include <STC15F2K60S2.H>
#include "led.h"
#include "key.h"
#include "init.h"
u8 led_show[8] = {0,0,0,0,0,0,0,0};
u8 led_scan;
u8 led_duty = 0;//led占空比
u8 key_slow;
u8 key_val,key_down,key_up,key_old;
u8 mode = 0;
u16 count;
void key_pro()
{
if(key_slow) return;
key_slow = 1;
key_val = key_read();
key_down = key_val & (key_old ^ key_val);
key_up = ~key_val & (key_old ^ key_val);
key_old = key_val;
switch(key_down)
{
case 16:
if(++mode == 4) mode = 0;
TR1 = 1;//定时器1开始计时
break;
}
}
void led_pro()//设置四种占空比
{
if(mode == 0)
led_duty = 10;
else if(mode == 1)
led_duty = 30;
else if(mode == 2)
led_duty = 60;
else if(mode == 3)
led_duty = 90;
}
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void timer0() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_scan == 8) seg_scan = 0;
seg(seg_scan,seg_show[seg_scan],seg_point[seg_scan]);
}
//设置定时器1为100us进行定时
void Timer1_Init(void) //100微秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x50; //设置定时初始值
TH1 = 0xFB; //设置定时初始值
TF1 = 0; //清除TF1标志
ET1 = 1;
EA = 1;
}
void timer1() interrupt 3
{
if(++led_scan == 8) led_scan = 0;
led(led_scan,led_show[led_scan]);
++count;
if(count <= led_duty)
{
led_show[0] = 0;
}
else if(count < 100)
{
led_show[0] = 1;
}
else if(count == 100)
{
count = 0;
led_show[0] = 0;
}
}
void main()
{
init();
Timer0_Init();
Timer1_Init();
while(1)
{
key_pro();
led_pro();
}
}
可自行修改
附录:文章来源:https://www.toymoban.com/news/detail-423456.html
文章来源地址https://www.toymoban.com/news/detail-423456.html
到了这里,关于蓝桥杯单片机知识点整合——临时抱佛脚的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!