main.c
c#include <reg52.h>
#include <intrins.h>
#include "lcd1602.h" /* 1602显示驱动文件 调用init和显示字符串2个函数 */
#include "ds18b20.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned int uint;
typedef unsigned char uchar;
//以下是C调低音的音频宏定义
#define L1 262 //将"L1"宏定义为低音"1"的频率262Hz 时间是1/262=3826/2 us 取半周期
#define L2 286 //将"L2"宏定义为低音"2"的频率286Hz
#define L3 311 //将"L3"宏定义为低音"3"的频率311Hz
#define L4 349 //将"L4"宏定义为低音"4"的频率349Hz
#define L5 392 //将"L5"宏定义为低音"5"的频率392Hz
#define L6 440 //将"l_a"宏定义为低音"6"的频率440Hz
#define L7 494 //将"L7"宏定义为低音"7"的频率494Hz
//以下是C调中音的音频宏定义
#define Z1 523 //将"Z1"宏定义为中音"1"的频率523Hz
#define Z2 587 //将"Z2"宏定义为中音"2"的频率587Hz
#define Z3 659 //将"Z3"宏定义为中音"3"的频率659Hz
#define Z4 698 //将"Z4"宏定义为中音"4"的频率698Hz
#define Z5 784 //将"Z5"宏定义为中音"5"的频率784Hz
#define Z6 880 //将"Z6"宏定义为中音"6"的频率880Hz
#define Z7 987 //将"Z7"宏定义为中音"7"的频率523H
//以下是C调高音的音频宏定义
#define H1 1046 //将"H1"宏定义为高音"1"的频率1046Hz
#define H2 1174 //将"H2"宏定义为高音"2"的频率1174Hz
#define H3 1318 //将"H3"宏定义为高音"3"的频率1318Hz
#define H4 1396 //将"H4"宏定义为高音"4"的频率1396Hz
#define H5 1567 //将"H5"宏定义为高音"5"的频率1567Hz
#define H6 1760 //将"H6"宏定义为高音"6"的频率1760Hz
#define H7 1975 //将"H7"宏定义为高音"7"的频率1975Hz
/* ****************************************** */
// ******** 硬件端口定义
/* ****************************************** */
sbit sound = P2 ^ 3; //蜂鸣器
/* ****************************************** */
// ******** 程序变量定义
/* ****************************************** */
unsigned int C; //储存定时器的定时常数
unsigned char u, t; //音乐所用的变量
unsigned char velocity = 50; //控制节拍使用的 这里100表示一个拍子100ms
/* ****************************************** */
// ******** 音乐0 天空之城
/* ****************************************** */
//以下是《天空之城》简谱 //每行对应一小节音符
unsigned int code music0[]=
{ Z6,Z7,/**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1,/**/Z5,Z3,Z3, /**/Z4,Z3,Z4,H1,
Z3,H1,H1,H1,/**/Z7,Z4,Z4,Z7,/**/Z7,Z6,Z7, /**/H1,Z7,H1,H3,/**/Z7,Z3,Z3, /**/Z6,Z5,Z6,H1,
Z5, Z3,/**/Z4,H1,Z7,H1,/**/H2,H2,H2,H1,/**/H1,Z6,Z7,Z5,/**/Z6,H1,H2, /**/H3,H2,H3,H5,
H2,Z5,Z5, /**/H1,Z7,H1,H3,/**/H3, /**/Z6,H1,Z7,H2,/**/H1,Z5,Z5, /**/H4,H3,H2,H1,
H3, /**/Z3,H3, /**/H6,H5,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,H5,/**/H3,H3,
H6,H5, /**/H3,H2,H1,H1,/**/H2,H1,H2,Z7,/**/Z6,Z6,Z7, /**/Z6,0xff}; //以0xff作为音符的结束标志
//以下是简谱中每个音符的节拍
//"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位
unsigned char code music0_JP[ ]=
{ 4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,4,12,
20,4,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8, /**/20,4,4, /**/12,4,8,8,
32, 4, /**/8,4,6,8, /**/4,4,4,16, /**/8,4,6,8, /**/24,4,4, /**/12,4,8,8,
24,4,4, /**/4,4,8,8, /**/32, /**/4,8,8,6, /**/12,4,16, /**/8,8,8,8,
30, /**/20,8, /**/16,8,8, /**/4,4,16,8, /**/8,4,4,8, /**/20,8,
16,16, /**/4,20,8, /**/8,4,4,8, /**/20,4,4, /**/32};
/* ****************************************** */
/* ******** 延时100ms 控制音乐节拍 */
/* ****************************************** */
void delay1()
{
uint i, j;
for ( i = 0; i < velocity; i++ )
for ( j = 0; j < 125; j++ )
;
}
/*********************************************************************************
* 【函 数 名】: void SerInit(void)
* 【功 能】: 串口初始化程序 设置波特率为9600
**********************************************************************************/
//void SerInit( void )
//{
// TMOD = 0x20; /* 用定时器设置串口波特率 9600 */
// TH1 = 0xfd; /* 使用定时器1作为波特率发生器 9600波特率 */
// TL1 = 0xfd;
// TR1 = 1;
// REN = 1; /* 串口初始化 */
// SM0 = 0;
// SM1 = 1;
// EA = 1; /* 开启总中断 */
// ES = 1; /* 串口中断 */
//}
#define FSOC 11059200L //晶振
#define BAUD 9600 //波特率
/*
*********************************************************************************************************
* 函 数 名: bsp_InitUart
* 功能说明: 初始化CPU的U串口硬件设备。未启用中断。
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void SerInit(void)
{
SCON = 0x50; /* 010 1 0000B,工作方式1, 8位UART,波特率可变,允许接收 */
TMOD = 0x20; /* T1工作于方式2 */
TCON = 0x40; /* 定时器1开始计数 */
TH1 = -(FSOC/BAUD/12/16); /* T1计数初值 */
TL1 = -(FSOC/BAUD/12/16);
PCON = 0x80; /* SMOD置1,双倍速率 */
RI = 0;
TI = 0;
ES = 1;//中断
EA = 1;//总中断
}
/*********************************************************************************
* 【函 数 名】: void send_cmd(unsigned char dat)
* 【功 能】: 串口发送数据命令
**********************************************************************************/
void send(unsigned char dat) {
SBUF = dat; //发送指令到SBUF
while (!TI)
; //等待发送结束
TI = 0; //清除结束标志,以便再发送数据
}
/*********************************************************************************
* 【函 数 名】: Print_Str(unsigned char *s)
* 【功 能】: 串口发送 一个字符串
**********************************************************************************/
void Print_Str(unsigned char *s) {
while (*s != '\0') {
send(*s++);
}
}
/* 显示温度 */
void DisplayTEMP( int value )
{
unsigned char disp[15];
unsigned char count=0;
if ( value >= 0 )
{
disp[count++] = ' ';
} else {
disp[count++] = '-';
}
disp[count++] = '0' + value % 1000 / 100;
disp[count++] = '0' + value % 100 / 10;
disp[count++] = '.';
disp[count++] = '0' + value % 10;
disp[count++] = 0xdf;
disp[count++] = 'C';
disp[count++] = 0;
LCD_write_str( 5, 0, disp );
}
/* pwm初始化定时器0 */
void init_timer0_pwm( void )
{
TMOD &= 0xf0;
TMOD |= 0x01; /* 定时器1为工作方式1 16bit */
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
ET0 = 1; /* 开定时器1中断 */
TR0 = 1; /* 关闭定时器 */
EA = 1; /* 开总开关 */
}
/* 音乐初始化定时器0 */
void init_timer0_yinyue( void )
{
TMOD &= 0xf0;
TR0 = 1;
ET0 = 1; /* 定时器T1中断允许 */
EA = 1; /* 开总中断 */
}
int temp;//温度
u8 pwm_count = 0;
u8 ZHANKONGBI = 5; /* 值越大 小灯越亮 */
char Txd_data = 0; //串口接收的数据
char mode = 0; //模式0PWM 模式1音乐 模式2温度 其他模式值无所谓
/* ****************************************** */
/* ******** 主函数 程序逻辑 */
/* ****************************************** */
sbit DULA = P2 ^ 6;
sbit WELA = P2 ^ 7;
sbit D6RL = P0 ^ 6;
void main()
{
LCD_init();//初始化
LCD_write_str( 0, 1, "hello~" );
SerInit();
Print_Str("test");//测试用
DULA=1;
P0=0X00;
DULA=0;
WELA=1;
P0=0X00;
WELA=0;
while ( 1 )
{
if ( mode == 1 )
{
u = 0; /* 从第1个音符f[0]开始播放 */
while ( music0[u] != 0xff ) /* 只要没有读到结束标志就继续播放 */
{
C = 460830 / music0[u];
TH0 = (8192 - C) / 32; /* 可证明这是13位计数器TH0高8位的赋初值方法 5 */
TL0 = (8192 - C) % 32; /* 可证明这是13位计数器TL0低5位的赋初值方法 */
TR0 = 1; /* 启动定时器T0 */
for ( t = 0; t < music0_JP[u]; t++ ) /* 控制节拍数 */
delay1(); /* 延时1个节拍单位 */
TR0 = 0; /* 关闭定时器T1 */
u++; /* 播放下一个音符 */
}
TR0 = 0; /* 关闭定时器 */
sound = 1; /* 关闭蜂鸣器 */
}else if ( mode == 2 )
{
temp = getTmpValue();
DisplayTEMP( temp );
sound = 1;
delayMs(10);
}
}
}
void Uart_isr() interrupt 4 /* 中断接收程序 */
{
if ( RI ) /* 判断是否接收完,接收完成后,由硬件置RI位 */
{
Txd_data = SBUF; /* 读入缓冲区 */
RI = 0; /* 清标志 */
SBUF = Txd_data;
while ( !TI )
; /* 等待发送结束 */
TI = 0; /* 清除结束标志,以便再发送数据 */
if ( Txd_data == '1' )
{
WELA=1;
P0=0X00;
WELA=0;
mode = 0;
init_timer0_pwm();
}else if ( Txd_data == '2' )
{
if ( ZHANKONGBI < 9 )
ZHANKONGBI++;
SBUF = '0' + ZHANKONGBI;
while ( !TI )
; /* 等待发送结束 */
TI = 0; /* 清除结束标志,以便再发送数据 */
}else if ( Txd_data == '3' )
{
if ( ZHANKONGBI > 0 )
ZHANKONGBI--;
SBUF = '0' + ZHANKONGBI;
while ( !TI )
; /* 等待发送结束 */
TI = 0; /* 清除结束标志,以便再发送数据 */
}else if ( Txd_data == '4' )
{
init_timer0_yinyue();
mode = 1;
WELA=1;
P0=0X00;
WELA=0;
}else if ( Txd_data == '5' )
{
mode = 5;
WELA = 1; /* 改变电压之前先拉高 */
D6RL = 1;
WELA = 0; /* 改变完了就拉低锁存 */
}else if ( Txd_data == '6' )
{
mode = 5;
WELA = 1; /* 改变电压之前先拉高 */
D6RL = 0;
WELA = 0; /* 改变完了就拉低锁存 */
}else if ( Txd_data == '7' )
{
mode = 2;
WELA=1;
P0=0X00;
WELA=0;
}
}
}
sbit LED = P1 ^ 0;
/* ==================定时器1中断服务程序=============== */
void timer0_server( void )
interrupt 1
{
/* mode=0 pwm */
if ( mode == 0 )
{
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
pwm_count++;
if ( pwm_count == 10 )
{
pwm_count = 0;
LED = 0;
}
if ( ZHANKONGBI == pwm_count )
{
LED = 1;
}
}else if ( mode == 1 )
{
/* mode=1 yinyue */
sound = !sound; /* 将P3.7引脚输出电平取反,形成方波 */
TH0 = (8192 - C) / 32; /* 可证明这是13位计数器TH0高8位的赋初值方法 */
TL0 = (8192 - C) % 32; /* 可证明这是13位计数器TL0低5位的赋初值方法 */
}
}
ds18b20.h
c#include <reg52.h>
#include <intrins.h>
#include <math.h>
sbit ds = P2^2;
/******************************************/
//延时n ms
/******************************************/
void delayMs(unsigned int a)
{
unsigned int i, j;
for(i = a; i > 0; i--)
for(j = 100; j > 0; j--);
}
/******************************************/
//初始化
/******************************************/
void dsInit()
{
unsigned int i;
ds = 0;
i = 100;
while(i>0) i--;
ds = 1;
i = 4;
while(i>0) i--;
}
void dsWait()
{
unsigned int i;
while(ds);
while(~ds);
i = 4;
while(i > 0) i--;
}
/******************************************/
//读取一位
/******************************************/
bit readBit()
{
unsigned int i;
bit b;
ds = 0;
i++;
ds = 1;
i++; i++;
b = ds;
i = 8;
while(i>0) i--;
return b;
}
/******************************************/
//读取一个字节
/******************************************/
unsigned char readByte()
{
unsigned int i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)
{
j = readBit();
dat = (j << 7) | (dat >> 1);
}
return dat;
}
/******************************************/
//写入一个字节
/******************************************/
void writeByte(unsigned char dat)
{
unsigned int i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)
{
b = dat & 0x01;
dat >>= 1;
if(b)
{
ds = 0; i++; i++;
ds = 1;
i = 8; while(i>0) i--;
}
else
{
ds = 0;
i = 8; while(i>0) i--;
ds = 1;
i++; i++;
}
}
}
/******************************************/
//发送读取命令
/******************************************/
void sendChangeCmd()
{
dsInit();
dsWait();
delayMs(1);
writeByte(0xcc);
writeByte(0x44);
}
/******************************************/
//发送读取命令
/******************************************/
void sendReadCmd()
{
dsInit();
dsWait();
delayMs(1);
writeByte(0xcc);
writeByte(0xbe);
}
/******************************************/
//获取温度 扩大了10倍
/******************************************/
int getTmpValue()
{
unsigned int tmpvalue;
int value;
float t;
unsigned char low, high;
EA=0;
sendChangeCmd();//ds18b20
EA=1;
//delayMs(1000);
EA=0;
sendReadCmd();
low = readByte();
high = readByte();
EA=1;
tmpvalue = high;
tmpvalue <<= 8;
tmpvalue |= low;
value = tmpvalue;
t = value * 0.0625;
value = t * 10 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
return value;
}
lcd1602.h
c#include <reg52.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
LCD_init();
LCD_write_str(1,1,"2223123");
*/
sbit lcd_rs=P3^5;
sbit lcd_rw=P3^6;
sbit lcd_en=P3^4;
#define DataPort P0
#define RS_CLR lcd_rs=0
#define RS_SET lcd_rs=1
#define RW_CLR lcd_rw=0
#define EN_CLR lcd_en=0
#define EN_SET lcd_en=1
void delay_lcd_ms(unsigned int a) {
unsigned int i, j;
for (i = a; i > 0; i--)
for (j = 100; j > 0; j--)
;
}
//***********************************************************************
// 显示屏命令写入函数
//***********************************************************************
void LCD_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
EN_SET;
DataPort = com; //命令写入端口
delay_lcd_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏数据写入函数
//***********************************************************************
void LCD_write_data(unsigned char dataa)
{
RS_SET;
RW_CLR;
EN_SET;
DataPort = dataa; //数据写入端口
delay_lcd_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏字符串写入函数
//***********************************************************************
void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_write_com(0x80 + x); //第一行显示
}
else
{
LCD_write_com(0xC0 + x); //第二行显示
}
while (*s)
{
LCD_write_data( *s);
s ++;
}
}
//***********************************************************************
// 显示屏初始化函数
//***********************************************************************
void LCD_init(void)
{
LCD_write_com(0x38); //显示模式设置
delay_lcd_ms(5);
LCD_write_com(0x38); //显示模式设置
delay_lcd_ms(5);
LCD_write_com(0x38); //显示模式设置
delay_lcd_ms(5);
LCD_write_com(0x38); //显示模式设置
delay_lcd_ms(5);
LCD_write_com(0x08); //显示关闭
delay_lcd_ms(5);
LCD_write_com(0x01); //显示清屏
delay_lcd_ms(5);
LCD_write_com(0x06); //显示光标移动设置
delay_lcd_ms(5);
LCD_write_com(0x0C); //显示开及光标设置
delay_lcd_ms(5);
}
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!