一年多没碰51单片机了,当时还是为STM32过渡学习的。
这期开了单片机专业课,不得不重拾起来。想吐槽的就是,课上还用的proteus而不是实物,去年自学我好歹还五十来块,买了个普中的。
大前天上午开了节实验课,一共五个实验。
- 流水灯
- 外部中断
- 数码管,定时器
- 矩阵键盘,串口
- 空调模拟。。。。。。。
前天晚上都做完了,算是初步掌握了proteus简单操作吧。本想用DS18B20测温,百度搜了加热元器件无果,就用灯泡指望灯丝加热,降温用一个风扇转转,做一个仿真真正能闭环控制的,但是proteus好像无法仿真出环境温度的变化。模拟不出来就模拟不出来吧,做出来的意思到了就行。
DS18B20有点玄乎,初始化时序那边在proteus上面需要改改,不然失败了,就只显示000.60还是什么数字来着。按理说当时实物也用的普中例程里面的能运行才对。时序数值稍改了一下,能正常读值测温了。显示部分用的数码管,懒得在仿真上面费工夫再去弄LCD1602了,有得有失吧,弊端就是读DS18B20温度时,读取函数放在数码管显示测得温度和按钮设定温度之间,时间超出了视觉停留,会带点闪动。用1602就没这问题了,但玩过实物了,仿真没兴趣。矩阵键盘仿真图里面放了,但没有使用到,用了两个带外部中断的按钮,实现增温减温的功能,代替了矩阵键盘,仿真原理图里面没有删去,没啥大碍。大灯泡和风扇都用了个继电器。风扇没用PWM波去驱动,图省事,接电就转。想想了,好像也没啥了。
总的来说,难度一般,没有队里去年51任务最后一个难度大,要求做个万年历带温度,密码锁,串口上位机能修改时间,设定闹铃时间,闹铃关还是开等等。
对了,上面忘了提及了,左边是检测温度,右边是设定温度。
用的多文件,proteus7版本的,keil4写的。都是老版本莫得问题的话,应该都能打开吧。用惯了keil5,再看看4真的简陋,喵的,而且结合32的CubeMX,更香。习惯了32的变量类型方式,uint8_t就是uchar,依此类推,或者详见typedef.h文件。
代码里面有些部分可能没用到,但问题不大,工程是几个实验慢慢添补的。没记错的话,定时器那边计数还是给交通灯实验三开着的没关。
如果是我同学看到了这个,起码把原理图位置改改,代码函数变量改改,别照搬。我还要写实验报告呢,课上我这实验也演示过了,雷同可不好哦。
做完算是分享吧,如果该文件有什么问题,可以私信我
单片机源程序如下:
- #include "reg52.h"
- #include "tydefine.h"
- #include "led.h"
- #include "timer.h"
- #include "exit.h"
- #include "ds18b20.h"
- #define GPIO_KEY P1
- sbit LSA = P2^2;
- sbit LSB = P2^3;
- sbit LSC = P2^4;
- sbit FAN = P2^6;
- sbit LAMP = P2^7;
- extern uint16_t SetTemNum;
- uint16_t CurrentTemNum = 0;
- uint8_t code DigitalTubeSegment[] ={
- 0x3f,0x06,0x5b,0x4f,0x66,
- 0x6d,0x7d,0x07,0x7f,0x6f
- };
- uint8_t KeyValue = 0;
- uint8_t DisplayData[8];
- void delay_ms(uint32_t n);
- void KeyDown();
- void UsartInit();
- void DigitalTubeDisplay(uint8_t ShowNumber,uint8_t DigitNumber);
- void DisplayCurrentNumber(uint16_t CurrentNumber);
- void datapros(int32_t temp);
- void TemJudgement();
- void main()
- {
- Exit0Init();
- Exit1Init();
- while(1)
- {
- datapros(Ds18b20ReadTemp());
- DigitalTubeDisplay(DisplayData[2],6);
- DigitalTubeDisplay(DisplayData[3],5);
- TemJudgement();
- datapros(Ds18b20ReadTemp());
- DisplayCurrentNumber(SetTemNum);
- TemJudgement();
- }
- }
- void delay_ms(uint32_t n)
- {
- uint32_t i=0,j=0;
- for(i=0;i<n;i++)
- for(j=0;j<123;j++);
- }
- void KeyDown()
- {
- uint8_t KeyWaitcount = 0;
- GPIO_KEY = 0x0F;
- if(GPIO_KEY != 0x0F)
- {
- delay_ms(10);
- if(GPIO_KEY != 0x0F)
- {
- switch(GPIO_KEY)
- {
- case 0x07:
- KeyValue = 1;
- break;
- case 0x0B:
- KeyValue = 2;
- break;
- case 0x0D:
- KeyValue = 3;
- break;
- case 0x0E:
- KeyValue = 4;
- break;
- }
- GPIO_KEY = 0xF0;
- switch(GPIO_KEY)
- {
- case 0xE0:
- KeyValue = KeyValue;
- break;
- case 0xD0:
- KeyValue = KeyValue + 4;
- break;
- case 0xB0:
- KeyValue = KeyValue + 8;
- break;
- case 0x70:
- KeyValue = KeyValue + 12;
- break;
- }
- while((KeyWaitcount<50)&&(GPIO_KEY != 0xF0))
- {
- delay_ms(10);
- KeyWaitcount++;
- }
- // SBUF = KeyValue;
- // while(!TI);
- // TI = 0;
- }
- }
- }
- void DigitalTubeDisplay(uint8_t ShowNumber,uint8_t DigitNumber)
- {
- switch(DigitNumber)
- {
- case 1:
- LSC = 0;LSB = 0;LSA = 0;
- break;
- case 2:
- LSC = 0;LSB = 0;LSA = 1;
- break;
- case 3:
- LSC = 0;LSB = 1;LSA = 0;
- break;
- case 4:
- LSC = 0;LSB = 1;LSA = 1;
- break;
- case 5:
- LSC = 1;LSB = 0;LSA = 0;
- break;
- case 6:
- LSC = 1;LSB = 0;LSA = 1;
- break;
- }
- P0 = DigitalTubeSegment[ShowNumber];
- delay_ms(1);
- P0 = 0x00;
- }
- void DisplayCurrentNumber(uint16_t CurrentNumber)
- {
- uint8_t UnitsDigit = 0;
- uint8_t TensDigit = 0;
- TensDigit = CurrentNumber/10;
- UnitsDigit = CurrentNumber%10;
- switch(3)
- {
- case 1:
- DigitalTubeDisplay(TensDigit,6);
- DigitalTubeDisplay(UnitsDigit,5);
- break;
- case 2:
- DigitalTubeDisplay(TensDigit,4);
- DigitalTubeDisplay(UnitsDigit,3);
- break;
- case 3:
- DigitalTubeDisplay(TensDigit,2);
- DigitalTubeDisplay(UnitsDigit,1);
- break;
- }
- }
- void datapros(int32_t temp)
- {
- float tp;
- if(temp< 0) //当温度值为负数
- {
- DisplayData[0] = 0x40; // -
- //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
- temp=temp-1;
- temp=~temp;
- tp=temp;
- temp=tp*0.0625*100+0.5;
- //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
- //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
- //算加上0.5,还是在小数点后面。
-
- }
- else
- {
- DisplayData[0] = 0x00;
- tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
- //如果温度是正的那么,那么正数的原码就是补码它本身
- temp=tp*0.0625*100+0.5;
- //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
- //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
- //算加上0.5,还是在小数点后面。
- }
- // DisplayData[1] = temp / 10000;
- DisplayData[2] = temp % 10000 / 1000;
- DisplayData[3] = temp % 1000 / 100;
- CurrentTemNum = DisplayData[2]*10 + DisplayData[3];
- // DisplayData[4] = temp % 100 / 10;
- // DisplayData[5] = temp % 10;
- }
- void TemJudgement()
- {
- // CurrentTemNum SetTemNum
- if(CurrentTemNum > SetTemNum)
- {
- FAN = 0;
- LAMP = 1;
- }
- else if(CurrentTemNum < SetTemNum)
- {
- FAN = 1;
- LAMP = 0;
- }
- }
复制代码
所有资料51hei提供下载:
06085.zip
(117.08 KB, 下载次数: 55)
|