STC12C5A60S2最小系统板/51单片机温度显示和温度控制风扇

您所在的位置:网站首页 ad18原理图生成pdf STC12C5A60S2最小系统板/51单片机温度显示和温度控制风扇

STC12C5A60S2最小系统板/51单片机温度显示和温度控制风扇

#STC12C5A60S2最小系统板/51单片机温度显示和温度控制风扇| 来源: 网络整理| 查看: 265

STC12C5A60S2最小系统板/51单片机温度显示和温度控制风扇,板载有DS18B20和TM1650+4位数码管。

项目简介

单片机课课程设计,要做一个智能温控风扇,达到设定的下限温度值就开启风扇,温度在上限和下限之间就按比例输出PWM占空比控制风扇,超过上限值就风扇全速。 使用STC12C5A60S2单片机,温度传感器用的DS18B20,数码管用TM1650芯片驱动,通过I2C与TM1650通信。 这个开源项目也可以直接当STC12C5A60S2最小系统,所有IO口都引出了。

STC12C5A60S2简介

STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机。它是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。

TM1650

TM1650 是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路。内部集成有MCU输入输出控制数字接口、数据锁存器、LED 驱动、键盘扫描、辉度调节等电路。TM1650 性能稳定、质量可靠、抗干扰能力强,可适用于24 小时长期连续工作的应用场合。

两种显示模式:8段×4位和7段×4位支持单个按键7x4bit(28个按键)和组合按键(4个)8级亮度可调段驱动电流大于25mA,位驱动电流大于150mA高速2线串行接口(CLK,DAT)振荡方式:内置RC振荡内置上电复位电路内置数据锁存电路支持3-5.5V电源电压抗干扰能力强提供DIP16及SOP16封装 实物图

原理图

PCB

顶层:

底层:

元件购买地址 0805电阻样品本:https://s.click.taobao.com/oWjIgGu0805电容样品本:https://s.click.taobao.com/r9ea1Hu共阴数码管:https://u.jd.com/1ir7YWCTM1650芯片:https://s.click.taobao.com/pYveTFuDS18B20芯片:https://s.click.taobao.com/zaNQqFu

元器件购买推荐立创商城,优惠注册链接:https://activity.szlcsc.com/invite/D03E5B9CEAAE70A4.html

代码和资料

完整工程和各芯片数据手册的下载地址:https://url.zeruns.tech/AkHGU 提取码:6gzf

立创开源平台开源链接:https://url.zeruns.tech/46y43

main.c #include #include #include "TM1650.h" #include "DS18B20.h" #include "Key.h" sbit LED2 = P2 ^ 3; sbit LED3 = P2 ^ 4; sbit LED4 = P2 ^ 5; sbit FAN = P4 ^ 2; // 定义TM1650的显示数组 unsigned char code dig1[11] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40}; // 0、1、2、3、4、5、6、7、8、9、-//不带小数点 unsigned char code dig2[11] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef, 0x40}; // 0、1、2、3、4、5、6、7、8、9、-//带小数点 unsigned char code dig3[3] = {0x76, 0x38, 0x40}; // H、L、- // 定义计数变量 unsigned int count = 0, count1 = 0; // 计数值 // 温度上下限值 uint8_t H_Set = 50; uint8_t L_Set = 25; // 定义显示模式的枚举变量类型 typedef enum { H_mode = 0, // 上限温度设置 L_mode, // 下限温度设置 T_mode, // 温度显示 } Display_MODE; Display_MODE Display_mode = T_mode; uint16_t temp; // 定时器/计数器初始化 void Timer_Init() { EA = 1; // 使能总中断 AUXR |= 0x80; // 定时器0时钟1T模式 TMOD &= 0xF0; // 清零低四位,设置为16位计数器模式 TMOD |= 0x01; // 设置高四位为定时器模式0 TL0 = 0xCD; // 设置定时初始值 TH0 = 0xD4; // 设置定时初始值 TF0 = 0; // 清除TF0标志 TR0 = 1; // 定时器0开始计时 ET0 = 1; // 使能定时器0中断 AUXR &= 0xBF; // 定时器1时钟12T模式 TMOD &= 0x0F; // 设置定时器模式 TMOD |= 0x10; // 设置定时器模式 TL1 = 0x00; // 设置定时初始值 TH1 = 0xB8; // 设置定时初始值 TF1 = 0; // 清除TF1标志 TR1 = 1; // 定时器1开始计时 ET1 = 1; // 使能定时器1中断 } // 定时器/计数器0中断服务函数 void Timer0_Isr(void) interrupt 1 { TL0 = 0xCD; // 设置定时初始值 TH0 = 0xD4; // 设置定时初始值 count++; // 每隔1毫秒,计数值加1 count1++; } void Timer1_Isr(void) interrupt 3 { TL1 = 0x00; // 设置定时初始值 TH1 = 0xB8; // 设置定时初始值 key_status_check(0, KEY1); key_status_check(1, KEY2); key_status_check(2, KEY3); key_status_check(3, KEY4); } void PWMInit() { // 配置PWM CCON = 0; // Initial PCA control register // PCA timer stop running // Clear CF flag // Clear all module interrupt flag CL = 0; // Reset PCA base timer CH = 0; CMOD = 0x00; // 设置PCA定时器时钟为晶振频率/12,禁用PCA计数器溢出中断 CCAP0H = CCAP0L = 0x80; // PWM0 port output 50% duty cycle square wave CCAPM0 = 0x42; // 开启比较器功能,开启PWM0 AUXR1 |= 0x40; // 切换PWM输出IO到P4 CR = 1; // PCA timer start run } // https://blog.zeruns.tech void SetPwmDutyCycle(unsigned char dutyCycle) { // dutyCycle的范围可以是0到100,表示0%至100%的占空比。 unsigned char newValue = ((100 - dutyCycle) * 255) / 100; CCAP0H = CCAP0L = newValue; // 更新CCAP0L,从而改变PWM信号占空比 } // 主函数 void main() { TM_WrCmd(0x21); // 设置TM1650为8段×4位模式,并打开显示,亮度为2级 Timer_Init(); // 初始化定时器 Key_Init(); // 初始化按键状态机 P4M0 = 0x04; // 设置P4.2为推挽输出 P4M1 = 0x00; PWMInit(); // 初始化PWM SetPwmDutyCycle(0); // 设置PWM占空比为0 temp = GetTemp(); // https://blog.zeruns.tech while (1) // 死循环,反复执行以下操作 { if (count >= 100) // 每隔100毫秒执行一次 { count = 0; temp = GetTemp(); // 读取温度 if (Display_mode == T_mode) // 温度显示模式 { TM_WrDat(0x68, dig1[temp / 1000]); // 写入第1位的显示数据 TM_WrDat(0x6a, dig2[temp / 100 % 10]); // 写入第2位的显示数据 TM_WrDat(0x6c, dig1[temp / 10 % 10]); // 写入第3位的显示数据 TM_WrDat(0x6e, dig1[temp % 10]); // 写入第4位的显示数据 } if (Display_mode == H_mode) // 上限温度设置 { TM_WrDat(0x68, dig3[0]); // 数码管第1位显示 H TM_WrDat(0x6a, dig3[2]); // 数码管第2位显示 - TM_WrDat(0x6c, dig1[H_Set / 10]); // 写入第3位的显示数据 TM_WrDat(0x6e, dig1[H_Set % 10]); // 写入第4位的显示数据 } else if (Display_mode == L_mode) // 下限温度设置 { TM_WrDat(0x68, dig3[1]); // 数码管第1位显示 L TM_WrDat(0x6a, dig3[2]); // 数码管第2位显示 - TM_WrDat(0x6c, dig1[L_Set / 10]); // 写入第3位的显示数据 TM_WrDat(0x6e, dig1[L_Set % 10]); // 写入第4位的显示数据 } if (temp / 100 >= L_Set && temp / 100 SetPwmDutyCycle(100); // 设置占空比100% } else if (temp / 100 count1 = 0; LED3 = ~LED3; } if (key[0] == 1) // SW3模式切换 { if (Display_mode != 2) { Display_mode++; } else { Display_mode = 0; } key[0] = 0; } if (key[1] == 1) // SW4上键 { if (Display_mode == H_mode) { if (H_Set if (L_Set if (Display_mode == H_mode) { if (H_Set > 0) { H_Set--; } } else if (Display_mode == L_mode) { if (L_Set > 0) { L_Set--; } } key[2] = 0; } LED4 = ~LED4; } } TM1650.c #include "TM1650.h" #include #include // https://blog.zeruns.tech // 定义TM1650的引脚 sbit SCL_T = P2 ^ 0; // 串行时钟 sbit SDA_T = P2 ^ 1; // 串行数据 // 定义延时函数 void Delay5us_TM() //@11.0592MHz { unsigned char i; _nop_(); _nop_(); _nop_(); i = 10; while (--i) ; } void Delay1us_TM() //@11.0592MHz { _nop_(); } // TM1650起始位 void TM_Start() { SCL_T = 1; SDA_T = 1; Delay5us_TM(); SDA_T = 0; } // TM1650结束位 void TM_Stop() { SCL_T = 1; SDA_T = 0; Delay5us_TM(); SDA_T = 1; } // TM1650应答信号 void TM_Ack() { unsigned char timeout = 1; SCL_T = 1; Delay5us_TM(); SCL_T = 0; while ((SDA_T) && (timeout unsigned char i; SCL_T = 0; Delay1us_TM(); for (i = 0; i TM_Start(); Write_TM_Byte(add); // 显存地址 TM_Ack(); Write_TM_Byte(dat); // 显示数据 TM_Ack(); TM_Stop(); } // TM1650写命令 void TM_WrCmd(unsigned char Bri) { TM_Start(); Write_TM_Byte(0x48); // 显示模式 TM_Ack(); Write_TM_Byte(Bri); // 亮度控制 TM_Ack(); TM_Stop(); } TM1650.h #ifndef __TM1650_H_ #define __TM1650_H_ void TM_WrDat(unsigned char add, unsigned char dat); void TM_WrCmd(unsigned char Bri); #endif DS18B20.c #include "DS18B20.h" #include #include #define uchar unsigned char #define uint unsigned int // DS18B20的数据引脚 sbit DS = P2 ^ 2; // 延时函数,单位为微秒 void delay_us(uchar us) { while (us--) { _nop_(); } } // https://blog.zeruns.tech // 初始化DS18B20,返回0表示成功,返回1表示失败 bit DS18B20_Init() { bit i; DS = 1; // 释放总线 _nop_(); DS = 0; // 拉低总线至少480us,复位DS18B20 delay_us(480); DS = 1; // 释放总线 delay_us(20); // 等待15~60us i = DS; // 读取DS18B20的存在信号,0表示存在,1表示不存在 delay_us(70); // 等待60~240us DS = 1; // 释放总线 _nop_(); _nop_(); return (i); } // 向DS18B20写入一个字节 void DSWriteByte(uchar dat) { uchar i; for (i = 0; i uchar i, dat, j; for (i = 0; i uchar L, H; int temp; DS18B20_Init(); // 初始化DS18B20 DSWriteByte(0xcc); // 发送跳过ROM指令,忽略地址匹配过程 DSWriteByte(0x44); // 发送温度转换指令,开始测量温度并将结果存入暂存器中 DS18B20_Init(); // 初始化DS18B20 DSWriteByte(0xcc); // 发送跳过ROM指令,忽略地址匹配过程 DSWriteByte(0xbe); // 发送读取暂存器指令,准备读取温度数据 L = DSReadByte(); // 先读取低字节数据 H = DSReadByte(); // 再读取高字节数据 temp = H; temp uint8_t i; for (i = 0; i switch (KEY_Status[key_num][g_keyStatus]) { // 按键释放(初始状态) case KS_RELEASE: { // 检测到低电平,先进行消抖 if (KEY == 0) { KEY_Status[key_num][g_keyStatus] = KS_SHAKE; } } break; // 抖动 case KS_SHAKE: { if (KEY == 1) { KEY_Status[key_num][g_keyStatus] = KS_RELEASE; } else { KEY_Status[key_num][g_keyStatus] = KS_PRESS; } } break; // 稳定短按 case KS_PRESS: { // 检测到高电平,先进行消抖 if (KEY == 1) { KEY_Status[key_num][g_keyStatus] = KS_SHAKE; } } break; default: break; } if (KEY_Status[key_num][g_keyStatus] != KEY_Status[key_num][g_nowKeyStatus]) { // 当前状态为松开 并且 前一次状态为按下 if ((KEY_Status[key_num][g_keyStatus] == KS_RELEASE) && (KEY_Status[key_num][g_lastKeyStatus] == KS_PRESS)) { key[key_num] = 1; } KEY_Status[key_num][g_lastKeyStatus] = KEY_Status[key_num][g_nowKeyStatus]; KEY_Status[key_num][g_nowKeyStatus] = KEY_Status[key_num][g_keyStatus]; } } Key.h #ifndef __KEY_H #define __KEY_H #include /*定义按键IO*/ sbit KEY1 = P3 ^ 2; sbit KEY2 = P3 ^ 3; sbit KEY3 = P3 ^ 4; sbit KEY4 = P3 ^ 5; typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long uint32_t; extern uint8_t KEY_Status[4][3]; // 记录各按键状态 extern uint8_t key[4]; // 记录各按键是否稳定按下,1表示按键已按下,0表示按键没被按下 void Key_Init(void); void key_status_check(uint8_t key_num, uint8_t KEY); #endif 其他开源项目推荐 画了个 MSP430F149的最小系统板 开源出来了:https://blog.zeruns.tech/archives/713.htmlSTM32F030C8T6最小系统板和流水灯(原理图和PCB):https://blog.zeruns.tech/archives/715.htmlSY8205同步降压可调DCDC电源模块(原理图和PCB):https://blog.zeruns.tech/archives/717.html2011年全国电赛题-开关电源模块并联供电系统:https://blog.zeruns.tech/archives/718.html2007年电赛电源题:30到36V可调升压DCDC模块(UC3843):https://oshwhub.com/zeruns/36v-sheng-ya-dcdc-mo-kuai-uc3842 推荐阅读 高性价比和便宜的VPS/云服务器推荐: https://blog.vpszj.cn/archives/41.html怎样搭建个人博客:https://blog.zeruns.tech/archives/218.html我的世界服务器搭建教程:https://blog.zeruns.tech/tag/mc/STM32读取SHT3x系列温湿度传感器:https://blog.zeruns.tech/archives/700.html使用VSCode代替Keil实现STM32和51单片机的开发:https://blog.zeruns.tech/archives/690.html指点云 日本VPS 性能评测,1核1G 10兆 5G防御 仅需29.4元/月:https://blog.vpszj.cn/archives/1749.html雨云 宿迁 Gold 6146 高防云服务器性能测评:https://blog.vpszj.cn/archives/1725.html


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3