一年多沒碰51單片機了,當時還是為STM32過渡學習的。
這期開了單片機專業課,不得不重拾起來。想吐槽的就是,課上還用的proteus而不是實物,去年自學我好歹還五十來塊,買了個普中的。
大前天上午開了節實驗課,一共五個實驗。
- 流水燈
- 外部中斷
- 數碼管,定時器
- 矩陣鍵盤,串口
- 空調模擬。。。。。。。
前天晚上都做完了,算是初步掌握了proteus簡單操作吧。本想用DS18B20測溫,百度搜了加熱元器件無果,就用燈泡指望燈絲加熱,降溫用一個風扇轉轉,做一個仿真真正能閉環控制的,但是proteus好像無法仿真出環境溫度的變化。模擬不出來就模擬不出來吧,做出來的意思到了就行。
DS18B20有點玄乎,初始化時序那邊在proteus上面需要改改,不然失敗了,就只顯示000.60還是什么數字來著。按理說當時實物也用的普中例程里面的能運行才對。時序數值稍改了一下,能正常讀值測溫了。顯示部分用的數碼管,懶得在仿真上面費工夫再去弄LCD1602了,有得有失吧,弊端就是讀DS18B20溫度時,讀取函數放在數碼管顯示測得溫度和按鈕設定溫度之間,時間超出了視覺停留,會帶點閃動。用1602就沒這問題了,但玩過實物了,仿真沒興趣。矩陣鍵盤仿真圖里面放了,但沒有使用到,用了兩個帶外部中斷的按鈕,實現增溫減溫的功能,代替了矩陣鍵盤,仿真原理圖里面沒有刪去,沒啥大礙。大燈泡和風扇都用了個繼電器。風扇沒用PWM波去驅動,圖省事,接電就轉。想想了,好像也沒啥了。
總的來說,難度一般,沒有隊里去年51任務最后一個難度大,要求做個萬年歷帶溫度,密碼鎖,串口上位機能修改時間,設定鬧鈴時間,鬧鈴關還是開等等。
TIM圖片20200611110112.png (31.75 KB, 下載次數: 34)
下載附件
2020-6-11 11:01 上傳
批注 2020-06-11 111340.png (42.14 KB, 下載次數: 47)
下載附件
2020-6-11 11:14 上傳
對了,上面忘了提及了,左邊是檢測溫度,右邊是設定溫度。
用的多文件,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)
2020-6-11 11:10 上傳
點擊文件名下載附件
仿真及代碼 下載積分: 黑幣 -5
|