目录
- 包含模块:
- 代码
- 延时函数
- 锁存器
- IIC通讯
- 主程序代码
- 剩余模块
- NE555
- 串口接受数据
- 演示视频
包含模块:
S4:温度DS18B20
S8:超声波测距
S12:蜂鸣器响一下然后关闭
S16:按一下蜂鸣器响,再按一下关闭
S5:继电器吸合一下然后松开
S9:按一下继电器吸合,再按一下继电器松开
S13:按一下LED全亮,再按一下LED全灭
S17:短按一下晶体管右端数字加1,并同时将次数写进EEPROM里,长按将次数清零
S6:实时时钟
S10:NE555的测量(由于引脚冲突,将此模块新建一个工程进行测试)
S14:光敏电阻
S18:滑动变阻器
S7:根据滑动变阻器阻值开始DAC
S11:串口向电脑发送01,02,03,04四个数据
S15:串口向电脑发送字符串Helloworld
S19:串口向电脑发送所有用到的变量
总的来说,除了红外模块(不考)、NE555,串口接受上位机命令,这三个部分,其他都有测试到
代码
延时函数
#include "intrins.h"
void Delay(unsigned char xms) //@12.000MHz
{
while(xms--){
unsigned char data i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void Delay12us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 33;
while (--i);
}
锁存器
#include <STC15F2K60S2.H>
#include "Delay.h"
void InitHC138(unsigned char channel){
switch(channel){
case 0:P2 = (P2 & 0x1F) | 0x00;break;
case 4:P2 = (P2 & 0x1F) | 0x80;break;
case 5:P2 = (P2 & 0x1F) | 0xa0;break;
case 6:P2 = (P2 & 0x1F) | 0xc0;break;
case 7:P2 = (P2 & 0x1F) | 0xe0;break;
}
}
void outputp0(unsigned char channel,unsigned char dat){
InitHC138(0);
P0 = dat;
InitHC138(channel);
InitHC138(0);
}
void showsmg(unsigned char pos,unsigned char dat){
outputp0(7,0xff);
outputp0(6,(0x01 << (pos - 1)));
outputp0(7,dat);
Delay(1);
}
void initsys(){
outputp0(4,0xff);
outputp0(5,0x00);
outputp0(6,0xff);
outputp0(7,0xff);
}
IIC通讯
EEPROM写入(只写0x00这一个地址)
void eepromwrite(unsigned char dat){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(0x00);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
EEPROM读取(只读0x00这一个地址)
unsigned char eepromread(){
unsigned char ret;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(0x00);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ret;
}
AD转换(0x41为光敏电阻,0x43为滑动变阻器)
unsigned char AD(unsigned char addr){
unsigned char ret;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ret;
}
DAC
void DAC(unsigned char dat){
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
主程序代码
#include <STC15F2K60S2.H>
#include "Delay.h"
#include "InitHC138.h"
#include "onwire.h"
#include "iic.h"
#include "ds1302.h"
#include "stdio.h"
void showselect();
void scankey();
code unsigned char Seg_Table[17] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xbf
};
unsigned char mode = 4;//模式代号
bit cewen = 0;//防止无限嵌套
unsigned int temp = 0;//温度
unsigned int time = 0;//超声波时间
unsigned int distance = 0;//测距距离
unsigned char y5stat = 0x00;
unsigned char ledstat = 0xff;
bit buzzer = 0;//蜂鸣器状态
bit relay = 0;//继电器状态
bit led = 0;//led状态
unsigned int T = 0;//按下S17的次数
bit S17stat = 0;//S17状态
unsigned char count = 0;//计时
unsigned char ds1302readaddr[3] = {0x81,0x83,0x85};
unsigned char ds1302writeaddr[3] = {0x80,0x82,0x84};
unsigned char timertc[3] = {0x48,0x59,0x09};
unsigned int count_f = 0;//频率计数
unsigned int tmp = 0;//频率缓存
unsigned char count_t = 0;//读取1s
unsigned char ad01 = 0;//光敏电阻阻值
unsigned char ad03 = 0;//滑动变阻器阻值
unsigned int da = 0;//DAC
bit flag = 0;
//****************************************温度
void delaysmg(unsigned char xms){//数码管延时
while(xms--){
showselect();
Delay(1);
}
}
void ds13b20(){//测温驱动
unsigned char LSB,MSB;
unsigned char i;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
cewen = 1;
for(i = 0;i < 15;i++){
delaysmg(10);scankey();
}
cewen = 0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
temp = (MSB << 8) | LSB;
temp = temp * 6.25;
}
void showtemp(){
showsmg(1,Seg_Table[4]);
showsmg(5,Seg_Table[temp / 1000]);
showsmg(6,Seg_Table[temp / 100 % 10] & 0x7f);
showsmg(7,Seg_Table[temp / 10 % 10]);
showsmg(8,Seg_Table[temp % 10]);
}
//****************************************
//****************************************超声波
sbit TX = P1^0;
sbit RX = P1^1;
void fangbo(){
unsigned char i;
for(i = 0;i < 8;i++){
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
void ceju(){
CMOD = 0x00;
CL = 0x00;
CH = 0x00;
CF = 0;
CR = 0;
fangbo();
CR = 1;
while((RX == 1) && (CH < 0x17));
CR = 0;
if(RX == 0){
RX = 1;
time = (CH << 8) | CL;
distance = time * 0.17;
}else{
distance = 999;
}
}
void showdis(){
showsmg(1,Seg_Table[8]);
showsmg(5,Seg_Table[distance / 100 % 10]);
showsmg(6,Seg_Table[distance / 10 % 10] & 0x7f);
showsmg(7,Seg_Table[distance % 10]);
}
//****************************************
//****************************************蜂鸣器响一下
void buzzer01(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[2]);
}
//****************************************
//****************************************蜂鸣器状态取反
void buzzer02(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[6]);
if(buzzer == 1){
showsmg(8,Seg_Table[1]);
}else if(buzzer == 0){
showsmg(8,Seg_Table[0]);
}
}
//****************************************
//****************************************继电器吸合一下
void relay01(){
showsmg(1,Seg_Table[5]);
}
//****************************************
//****************************************蜂鸣器状态取反
void relay02(){
showsmg(1,Seg_Table[9]);
if(relay == 1){
showsmg(8,Seg_Table[1]);
}else if(relay == 0){
showsmg(8,Seg_Table[0]);
}
}
//****************************************
//****************************************LED全灭全亮
void ledshow(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[3]);
if(led == 1){
showsmg(8,Seg_Table[1]);
}else if(led == 0){
showsmg(8,Seg_Table[0]);
}
}
//****************************************
//****************************************按一下晶体管+1,并且存到EEPROM里面
void smgp1(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[7]);
showsmg(8,Seg_Table[T % 10]);
if(T > 9){
showsmg(7,Seg_Table[T / 10 % 10]);
}
if(T > 99){
showsmg(6,Seg_Table[T / 100 % 10]);
}
if(T > 999){
showsmg(5,Seg_Table[T / 1000 % 10]);
}
if(T > 9999){
showsmg(4,Seg_Table[T / 10000 % 10]);
}
}
//****************************************
//****************************************长短按定时器
void Timer2_Isr(void) interrupt 12
{
if(S17stat){
count++;
}
}
void Timer2_Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xF0; //设置定时初始值
T2H = 0xD8; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //使能定时器2中断
EA = 1;
}
//****************************************
//****************************************ds1302
void ds1302_config(){
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i = 0;i < 3;i++){
Write_Ds1302_Byte(ds1302writeaddr[i],timertc[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void ds1302_read(){
unsigned char i;
for(i = 0;i < 3;i++){
timertc[i] = Read_Ds1302_Byte(ds1302readaddr[i]);
}
}
void showrtc(){
ds1302_read();
showsmg(1,Seg_Table[timertc[2] / 16]);
showsmg(2,Seg_Table[timertc[2] % 16]);
showsmg(3,Seg_Table[16]);
showsmg(4,Seg_Table[timertc[1] / 16]);
showsmg(5,Seg_Table[timertc[1] % 16]);
showsmg(6,Seg_Table[16]);
showsmg(7,Seg_Table[timertc[0] / 16]);
showsmg(8,Seg_Table[timertc[0] % 16]);
}
//****************************************
//****************************************NE555(P34在使用,做不了)
/*void Timer0_Isr(void) interrupt 1
{
count_f++;
}
void Timer1_Isr(void) interrupt 3
{
if(count_t == 20){
count_t = 0;
tmp = count_f;
count_f = 0;
}
}
void Timer_Init(void) //@12.000MHz
{
TMOD = 0x07; //设置定时器模式
TL0 = 0xFF; //设置定时初始值
TL1 = 0xB0; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1;
}
void ne555show(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[0]);
showsmg(8,Seg_Table[tmp % 10]);
if(tmp > 9){
showsmg(7,Seg_Table[tmp / 10 % 10]);
}
if(tmp > 99){
showsmg(7,Seg_Table[tmp / 100 % 10]);
}
if(tmp > 999){
showsmg(7,Seg_Table[tmp / 1000 % 10]);
}
if(tmp > 9999){
showsmg(7,Seg_Table[tmp / 10000 % 10]);
}
}*/
//****************************************
//****************************************光敏电阻
void showad01(){
ad01 = AD(0x41);
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[4]);
showsmg(6,Seg_Table[ad01 / 100]);
showsmg(7,Seg_Table[ad01 / 10 % 10]);
showsmg(8,Seg_Table[ad01 % 10]);
}
//****************************************
//****************************************滑动变阻器器
void showad03(){
ad03 = AD(0x43);
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[8]);
showsmg(6,Seg_Table[ad03 / 100]);
showsmg(7,Seg_Table[ad03 / 10 % 10]);
showsmg(8,Seg_Table[ad03 % 10]);
}
//****************************************
//****************************************根据滑动变阻器阻值进行DAC
void showDAC(){
ad03 = AD(0x43);
DAC(ad03);
Delay(5);
da = ad03 * 100 / 51;
showsmg(1,Seg_Table[7]);
showsmg(5,Seg_Table[da / 100] & 0x7f);
showsmg(6,Seg_Table[da / 10 % 10]);
showsmg(7,Seg_Table[da % 10]);
}
//****************************************
//****************************************串口
unsigned char command = 0x00;//串口命令
void sendbyte(unsigned char dat);
void Uart1_Isr(void) interrupt 4
{
if(RI){
command = SBUF;
RI = 0;
}
}
void Uart1_Init(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCC; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
void sendbyte(unsigned char dat){
SBUF = dat;
while(TI == 0);
TI = 0;
}
/*void working(){//键盘引脚冲突,这部分也做不了
if(command != 0x00){
if(command == 0xa1){
printf("%d.%d",(int)(temp / 100),(int)(temp % 100));command = 0x00;
}
if(command == 0xa2){
printf("%d.%d",(int)(distance / 10),(int)(distance % 10));command = 0x00;
}
if(command == 0xa3){
printf("%d-%d-%d",(int)(timertc[2]),(int)(timertc[1]),(int)(timertc[0]));command = 0x00;
}
if(command == 0xa4){
printf("%d,%d,%d.%d",(int)(ad01),(int)(ad03),(int)(da / 100),(int)(da % 100));command = 0x00;
}
}
}*/
//****************************************
//****************************************显示选择
void showselect(){
switch(mode){
case 4:if(cewen == 0){ds13b20();}showtemp();break;
case 8:ceju();showdis();break;
case 12:buzzer01();break;
case 16:buzzer02();break;
case 5:relay01();break;
case 9:relay02();break;
case 13:ledshow();break;
case 17:smgp1();break;
case 6:showrtc();break;
//case 10:ne555show();break;
case 14:showad01();break;
case 18:showad03();break;
case 7:showDAC();break;
}
}
//****************************************
//****************************************按键扫描
void scankey(){
P33 = 0;P32 = 1;P31 = 1;P30 = 1;
P42 = 1;P40 = 1;P35 = 1;P34 = 1;
if(P44 == 0){//S4
Delay(5);
mode = 4;
while(P42 == 0){
showselect();
}
}
if(P42 == 0){//S8
Delay(5);
mode = 8;
while(P40 == 0){
showselect();
}
}
if(P35 == 0){//S12
Delay(5);
mode = 12;
while(P35 == 0){
showselect();
}
y5stat = y5stat | 0x40;outputp0(5,y5stat);
Delay(100);
y5stat = y5stat & ~0x40;outputp0(5,y5stat);
}
if(P34 == 0){//S12
Delay(5);
mode = 16;
buzzer = ~buzzer;
while(P34 == 0){
showselect();
}
if(buzzer == 1){
y5stat = y5stat | 0x40;outputp0(5,y5stat);
}else if(buzzer == 0){
y5stat = y5stat & ~0x40;outputp0(5,y5stat);
}
}
P33 = 1;P32 = 0;P31 = 1;P30 = 1;
P42 = 1;P40 = 1;P35 = 1;P34 = 1;
if(P44 == 0){//S5
Delay(5);
mode = 5;
while(P44 == 0){
showselect();
}
y5stat = y5stat | 0x10;outputp0(5,y5stat);
Delay(100);
y5stat = y5stat & ~0x10;outputp0(5,y5stat);
}
if(P42 == 0){//S9
Delay(5);
mode = 9;
relay = ~relay;
while(P42 == 0){
showselect();
}
if(relay == 1){
y5stat = y5stat | 0x10;outputp0(5,y5stat);
}else if(relay == 0){
y5stat = y5stat & ~0x10;outputp0(5,y5stat);
}
}
if(P35 == 0){//S13
Delay(5);
mode = 13;
led = ~led;
while(P35 == 0){
showselect();
}
if(led == 1){
ledstat = 0x00;outputp0(4,ledstat);
}else if(led == 0){
ledstat = 0xff;outputp0(4,ledstat);
}
}
if(P34 == 0){//S17
Delay(5);
mode = 17;
T = eepromread();Delay(2);
S17stat = 1;
while(P34 == 0){
showselect();
}
S17stat = 0;
if(count > 100){
count = 0;
T = 0;
}else if(count <= 100){
T++;
count = 0;
}
eepromwrite(T);Delay(2);
}
P33 = 1;P32 = 1;P31 = 0;P30 = 1;
P42 = 1;P40 = 1;P35 = 1;P34 = 1;
if(P44 == 0){//S6
Delay(5);
mode = 6;
while(P44 == 0){
showselect();
}
}
if(P42 == 0){//S10(NE555的P34引脚被占用,无法在此程序中检验,可以抽出来单独检验)
Delay(5);
mode = 10;
while(P42 == 0){
showselect();
}
}
if(P35 == 0){//S14
Delay(5);
mode = 14;
while(P35 == 0){
showselect();
}
}
if(P34 == 0){//S18
Delay(5);
mode = 18;
while(P34 == 0){
showselect();
}
}
P33 = 1;P32 = 1;P31 = 1;P30 = 0;
P42 = 1;P40 = 1;P35 = 1;P34 = 1;
if(P44 == 0){//S7
Delay(5);
mode = 7;
while(P44 == 0){
showselect();
}
}
if(P42 == 0){//S11
Delay(5);
sendbyte(0x01);
sendbyte(0x02);
sendbyte(0x03);
sendbyte(0x04);
while(P42 == 0){
showselect();
}
}
if(P35 == 0){//S15
Delay(5);
printf("HelloWorld");
while(P35 == 0){
showselect();
}
}
if(P34 == 0){//S19
Delay(5);
printf("tempreture:%d.%d,distance:%d.%d,",(int)(temp / 100),(int)(temp % 100),(int)(distance / 10),(int)(distance % 10));
printf("rtc:%d-%d-%d,trigger time:%d",(int)timertc[2],(int)timertc[1],(int)timertc[0]);
printf("light:%d,voltage:%d,dac:%d.%d",(int)ad01,(int)ad03,(int)(da / 100),(int)(da % 100));
while(P34 == 0){
showselect();
}
}
}
//****************************************
void main(){
ds1302_config();
Timer2_Init();
Uart1_Init();
initsys();
while(1){
scankey();
showselect();
//working();
}
}
char putchar(char ch){//重定向
sendbyte(ch);
return ch;
}
剩余模块
由于NE555需要用跳线帽连接SIGNAL和P34引脚,引发外部中断,但是矩阵键盘全给我用上了,导致扫描按键的时候,P34可能大部分时间都在高电平,因此无法正常计算NE555的频率。
标志位led调试

led调试串口
发现一直处于接受状态,然后我就尝试让单片机返还所接收到 数据
命令初始化为0x01,结果被改为00
结论:因为按键扫描,串口的波特率发生器一直在被干扰,导致串口可能一直处于接受状态,经过调试(设立标志位、返回发送的数据),发现一直接受到0x00的数据。
所以,这两部分都被独立出来进行检验。
NE555
#include <STC15F2K60S2.H>
#include "Delay.h"
#include "InitHC138.h"
code unsigned char Seg_Table[17] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xbf
};
unsigned int count_f = 0;//频率计数
unsigned int tmp = 0;//频率缓存
unsigned char count_t = 0;//读取1s
void Timer0_Isr(void) interrupt 1
{
count_f++;
}
void Timer1_Isr(void) interrupt 3
{
count_t++;
if(count_t == 20){
count_t = 0;
tmp = count_f;
count_f = 0;
}
}
void Timer_Init(void) //@12.000MHz
{
TMOD = 0x07; //设置定时器模式
TL0 = 0xFF; //设置定时初始值
TL1 = 0xB0; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1;
}
void ne555show(){
showsmg(1,Seg_Table[1]);
showsmg(2,Seg_Table[0]);
showsmg(8,Seg_Table[tmp % 10]);
if(tmp > 9){
showsmg(7,Seg_Table[tmp / 10 % 10]);
}
if(tmp > 99){
showsmg(6,Seg_Table[tmp / 100 % 10]);
}
if(tmp > 999){
showsmg(5,Seg_Table[tmp / 1000 % 10]);
}
if(tmp > 9999){
showsmg(4,Seg_Table[tmp / 10000 % 10]);
}
}
//****************************************
void main(){
Timer_Init();
initsys();
while(1){
ne555show();
}
}
串口接受数据
#include <STC15F2K60S2.H>
#include "Delay.h"
#include "InitHC138.h"
#include "stdio.h"
//****************************************串口
unsigned char command = 0x00;//串口命令
void sendbyte(unsigned char dat);
void Uart1_Isr(void) interrupt 4
{
if(RI){
sendbyte(command);
command = SBUF;
RI = 0;
}
}
void Uart1_Init(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCC; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
EA = 1;
}
void sendbyte(unsigned char dat){
SBUF = dat;
while(TI == 0);
TI = 0;
}
void working(){
if(command != 0x00){
if(command == 0xa1){
printf("0as");command = 0x00;
}
if(command == 0xa2){
printf("1sa");command = 0x00;
}
if(command == 0xa3){
printf("0xc");command = 0x00;
}
if(command == 0xa4){
printf("0qwe");command = 0x00;
}
}
}
//****************************************
//****************************************
void main(){
Uart1_Init();
initsys();
while(1){
working();
}
}
char putchar(char ch){//重定向
sendbyte(ch);
return ch;
}
演示视频
综合模块
综合DAC
综合串口(无接收)
串口接收数据
NE555
该博客围绕蓝桥杯单片机项目展开,介绍了包含的模块,如温度、超声波测距、蜂鸣器等功能模块,还给出了延时函数、锁存器、IIC通讯等代码。此外,提到剩余模块NE555因引脚冲突无法正常计算频率,以及串口接受数据等情况,除部分模块外均有测试。

3821

被折叠的 条评论
为什么被折叠?



