找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 37491|回復: 50
收起左側

藍橋杯單片機設計與開發(fā)賽前學習準備

  [復制鏈接]
回帖獎勵 2 黑幣 回復本帖可獲得 2 黑幣獎勵! 每人限 1 次(中獎概率 10%)
ID:231500 發(fā)表于 2018-2-11 22:16 | 顯示全部樓層 |閱讀模式
本帖最后由 13122031726 于 2018-2-13 16:29 編輯

原文出處:Bkoak’s blog  www點bkoak點com/2018/02/11/lanqiao1/

藍橋杯單片機設計與開發(fā)所需設備:
CT107D實驗平臺、IAP15F2K60S2轉接芯片(或最小系統(tǒng)板)

  • 必備開發(fā)軟件:
已注冊Keil5、 STC-ISP-v6.86
%E5%BF%85%E5%A4%87.png

注冊步驟:①打開keil5→File→License Mana…                   ②復制CID
%E6%AD%A5%E9%AA%A4%E4%B8%80.png                %E6%AD%A5%E9%AA%A4%E4%BA%8C.png

③打開keil5注冊機,按圖示選擇,并粘貼入自己的CID碼,復制最下面的LIC碼
%E6%AD%A5%E9%AA%A4%E4%B8%89-300x172.png
④返回License Mana…界面,將LIC碼粘貼,并點擊Add LIC
%E6%AD%A5%E9%AA%A4%E5%9B%9B-300x24.png
軟件安裝注意事項
①下載過程中請關閉所有殺毒軟件
②第一次開啟keil5,及keil5注冊機(有奇妙的音樂建議關閉聲音)時,請使用管理員模式運行。

  • 事前準備
1)STC-ISP-v6.86使用說明
①芯片及串口選擇                                                                              ②開發(fā)輔助功能(范例程序、定時器、延時計算器等)
isp1-208x300.png                                                           isp2-300x222.png

2)keil5工程創(chuàng)建說明
①導入頭文件(該操作只需一次)     選擇isp軟件keil仿真選項點擊圖中所示位置,選擇keil安裝目錄導入。
isp3-300x110.png                         isp4-258x300.png

②創(chuàng)建keil工程
(1)自定位置創(chuàng)建工程所需文件夾(中英文皆可)。
(2)打開Keil5→Project→New uVision Project
(3)選擇芯片(按圖示選擇,確認后彈出對話框選是)
keil1-300x232.png
(4)選擇生成HEX文件 點擊菜單 Project→Options for Target→Output(勾選圖示內容)
keil2-300x120.png
(5)創(chuàng)建C程序 點擊菜單 File→New→將其保存在工程目錄以“xxx.c”命名→導入工程文檔中(見圖)
keil3-300x168.png                keil4-300x155.png

賽前學習的準備工作到此就大致結束了,下一章內容將簡單介紹主要學習內容及相關資料下載。



新建了答疑群:693211073,即針對本次藍橋杯答疑,也解答一些單片機相關咨詢,將來也會開源一些我正在做的設計到該論壇,我的博客,以及交流群里,希望論壇管理員也能支持一下。(群新建,希望來一些朋友幫忙管理)

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-11 22:17 | 顯示全部樓層
爭取三月底比賽前更新完成省賽全部內容
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-11 23:35 | 顯示全部樓層
按題目格式搜索可以找到后續(xù)內容,同時在博客持續(xù)更新。
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-12 00:01 | 顯示全部樓層
上文芯片型號寫錯應該是IAP15F2K61S2,I/O位置功能全同STC15F2K60S2
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-12 00:48 | 顯示全部樓層
本帖最后由 13122031726 于 2018-2-12 01:17 編輯

第二部分

原文出處:Bkoak’s blog  www點bkoak點com/2018/02/11/lanqiao2/

  • CT107D單片機綜合實訓平臺

不推薦官方購買該平臺,很貴,建議用同類產品替換,或買二手的。
以下簡稱實訓平臺,該文章只介紹比賽使用部分模塊。
(1) 單片機芯片
配置 40 腳 51 系列單片機插座(比賽使用IAP15F2K61S2轉接芯片);
   %E8%BD%AC%E6%8E%A5-120x300.png
全I/O兼容8051系列,為保留P3.6,P3.7的WR,RD功能由P4.2,P4.4替換。
(2) 顯示模塊
配置8路led發(fā)光二極管;
配置8位8段共陽數(shù)碼管;
led-300x119.png
(2) 輸入/輸出模塊
配置 4×4 鍵盤矩陣,其中四個按鍵可通過跳線配置為獨立按鍵;
配置繼電器、蜂鳴器;
beep-300x130.png
(3) 傳感模塊
配置紅外一體頭 1838 及紅外發(fā)射管;
配置一個霍爾傳感器;
配置數(shù)字溫度傳感器 DS18B20;
Rled-127x300.png
(4)存儲/AD、DA/時鐘模塊
配置 EEPROM 芯片 AT24C02;
配置 PCF8591A/D、D/A 芯片,內含 8 位 4 通道 A/D 轉換、單通道 D/A 轉換;
配置時鐘芯片DS1302;
ee%E3%80%81ds.png     ad-256x300.png
(5)USB轉TTLIO拓展
配置 ch341進行USB轉串口進行程序下載;
配置4片74HC573進行IO復用;
配置138譯碼器與74HC02四2輸入或非門控制573片選;
573-300x115.png        13802-300x199.png

實訓平臺布局圖
各個基本功能模塊在實驗板上的布局如下圖所示。
%E5%8A%9F%E8%83%BD%E5%9B%BE-300x223.png
                原理圖文末下載
需使用跳線說明(詳見開發(fā)板)(1) 紅外功能選擇 跳線 ( J2 )
5、3 短接,6、4 短接:選擇紅外發(fā)射/接收功能
(2) USB 功能選擇(J4 )
1、2 短接:選擇 UART 功能,USB 接口用作串行通信
(3) 按鍵功能選擇(J5 )
1、2 短接:選擇 4×4 鍵盤功能
2、3 短接:選擇 4 個獨立按鍵功能
(4) 外設訪問方式選擇(J13 )
2、3 短接:選擇 I/O 口直接控制方式
(5) 外設訪問方式選擇 (J15 )
1、2 短接:選擇 51 系列單片機

管腳說明見PDF:P48文末下載
CH341驅動文末下載
  • 通過省賽必須掌握內容
1)片上功能(見datasheet文末下載
①定時器
②中斷
③捕獲
④串口
⑤外部中斷
⑥EEPROM
⑦ADC
2)重點外設功能(見后續(xù)文章)
①鍵盤
②數(shù)碼管、LED
③繼電器、蜂鳴器
④DS1302、AT24C02
⑤DS18B20
⑥PCF8591
2)額外功能(視情況更新)
①串口通信
②LCD1602
③紅外收發(fā)
④霍爾元件頻率測算
⑤超聲波測距

本章資料下載地址見原文

開發(fā)平臺簡介及主要學習內容的介紹到此就大致結束了,下一章將正式開始藍橋杯單片機教學。

評分

參與人數(shù) 1黑幣 +8 收起 理由
arthuryu + 8 贊一個!

查看全部評分

回復

使用道具 舉報

ID:263980 發(fā)表于 2018-2-12 09:11 | 顯示全部樓層
參加過,但是覺得很水
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-12 12:56 來自手機 | 顯示全部樓層
奮斗de小青年 發(fā)表于 2018-2-12 09:11
參加過,但是覺得很水

入門級嘛。學校交錢的就去一下。主要寫一下得獎的方法。聊勝于無
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-12 21:20 | 顯示全部樓層
本帖最后由 13122031726 于 2018-2-12 21:40 編輯

第三部分

原文出處:Bkoak’s blog  www點bkoak點com/2018/02/12/lanqiao3/


  • CT107D實驗平臺操作關鍵——器件原理部分
CT107D實驗平臺區(qū)別于其他51單片機及開發(fā)平臺的區(qū)別就在于該平臺在I/O口復用上的設計。
其中的關鍵就在于對138譯碼器、四2輸入或非門、573三態(tài)鎖存器的操作上,本章內容就將著重介紹這三部分的使用方法。
1)3線-8線譯碼器 —— 74HC138(電氣參數(shù)見datasheet文末下載
引腳分布                 芯片實物引腳順序見datasheet。
138譯碼器的工作原理是選通端(G1)為高電平,另兩個選通端((G2A)和(G2B))為低電平時,可將地址端(A、B、C)的二進制編碼在一個對應的輸出端以低電平譯出。
引出端符號:
A、B、C 譯碼地址輸入端(接單片機IO口)
G1 選通端(接電源或單片機IO口)
(G2A)、(G2B) 選通端(低電平有效)
Y0~Y7 譯碼輸出端(接受控器件)
在該平臺A、B、C 譯碼地址輸入端接入單片機P2寄存器中的P25、P26、P27三個端口。
真值表:
其中G2* =(G2A) + (G2B)、L = 低電平、H = 高電平、X = 任意
推薦代碼寫法:

  1. //如果需要使用P20~P25端口建議如下寫法
  2. P2 = ((P2&0x1f)|0xA0); //這種寫法只改變后P2高三位的狀態(tài),不改變前面低五位的狀態(tài)。
  3. //P2&0x1f的操作是保留低五位狀態(tài)將高三位置0,0x1f = 00011111  和  0xA0 = 10100000進行或運算  
  4. //最終 P2 = 0xBF = 10111111
  5. P2 = 0xA0; //如無需使用P20~P25端口可直接對P2寄存器進行操作
復制代碼





2)四2輸入或非門(OC)—— 74HC02(電氣參數(shù)見datasheet文末下載
引腳分布                 芯片實物引腳順序見datasheet。
四2輸入或非門(OC)為四組 2 輸入端或非門(正邏輯)。
引出端符號:
A1-A4或非門輸入端(接單片機IO口或GND)
B1-B4或非門輸入端(接單片機IO口或GND)
Y1~Y4 或非門輸出端(接受控器件)
在該平臺A1-A4或非門輸入端接入GND或P36(通過跳線選擇),B1-B4或非門輸入端接入GND,Y1~Y4 或非門輸出端接四片573(LE)鎖存使能端。
功能表:
其中A、B、Y為或非門輸入輸出端、L = 低電平、H = 高電平
未接單片機IO口不涉及直接操作代碼段。



3)八進制3態(tài)非反轉透明鎖存器 —— 74HC573(電氣參數(shù)見datasheet文末下載
引腳分布                 芯片實物引腳順序見datasheet。
573三態(tài)鎖存器是標準CMOS輸入/輸出器件,當鎖存使能端為高時,該器件為透明態(tài)(輸入同輸出);當鎖存使能端為低時,在符合建立時間和保持時間的數(shù)據(jù)會被鎖存。
引出端符號:
D1-D8輸入端(接單片機IO口)
Q1-Q8輸出端(接受控器件)
LE鎖存使能端(接控制器件)
OE輸出使能端(接GND)
在該平臺D1-D8輸入端接入單片機P0,Q1-Q8輸出端接受控元器件,LE鎖存使能端接四2或非門輸出端。
功能表:
其中Z為高阻態(tài)、L = 低電平、H = 高電平、X 不用關心
  • CT107D實驗平臺操作關鍵——代碼操作部分
  1. P2 = ((P2&0x1f)|0xA0); //操作138譯碼器ABC輸入端為 101,Y0~Y7輸出為 11111011,其中Y5為 L
  2. /*
  3. CT107D實驗平臺中 Y4~Y7分別對應控制或非門輸出端Y1~Y4
  4. 通過或非門選擇分別控制以下四部份的573鎖存器
  5.     ①LED發(fā)光二極管
  6.     ②達林頓管——(電機、繼電器、蜂鳴器)
  7.     ③8位8段數(shù)碼管段選
  8.     ④8位8段數(shù)碼管位選
  9. */
  10. P0 = 0x00; //控制②號573鎖存器驅動,達林頓管ULN2003輸出0xff,控制電機、繼電器、蜂鳴器等原件
復制代碼




本章資料下載地址見原文。

開發(fā)平臺關于138譯碼器、四2輸入或非門、573三態(tài)鎖存器的介紹到此就大致結束了,下一章將開始講解消音,點亮LED及流水燈。

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-12 23:31 | 顯示全部樓層
第三部分可以快點通過下審核嗎,,
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-13 15:11 來自手機 | 顯示全部樓層
本帖最后由 13122031726 于 2018-2-13 16:30 編輯

新建了答疑群:693211073,即針對本次藍橋杯答疑,也解答一些單片機相關咨詢,將來也會開源一些我正在做的設計到該論壇,我的博客,以及交流群里,希望論壇管理員也能支持一下。(群新建,希望來一些朋友幫忙管理)
回復

使用道具 舉報

ID:32289 發(fā)表于 2018-2-13 20:12 | 顯示全部樓層
這個只有純屬支持一下子了,沒有這個技術。
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-13 23:42 | 顯示全部樓層
rrqxx 發(fā)表于 2018-2-13 20:12
這個只有純屬支持一下子了,沒有這個技術。

互相交流學習嘛,大家都一樣,技術都是時間經驗積累的,不能一蹴而就。
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-14 00:43 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(4)消音,點亮LED及流水燈的操作

本章我們的主要內容分為三點
①   介紹如何開啟單片機電源后使其蜂鳴器、繼電器停止工作,因為開發(fā)板的設計中,開機后蜂鳴器是直接啟動的,需要通過操作寄存器使之關閉,不然會很影響工作。
②   點亮LED,并對LED進行一些簡單的操作說明。
③   教學流水燈程序的兩種寫法。
  • 一、消音、關閉繼電器
首先,我們先看這一部分的原理圖
大家可以從我第二篇博文下載原理圖自行查看,蜂鳴器和繼電器都是由達林頓管ULN2003來控制的,因為這兩個器件都屬于大電流器件不能通過單片機的IO口直接驅動,所以外加了電流放大的裝置,我們可以將ULN2003看做一個反向器或者是一個非門,所有TTL信號過來都會被取反取非。
繼電器和蜂鳴器分別接在ULN2003的out6和out7,這兩個管腳的輸入端in6和in7分別由U9這片573三態(tài)鎖存器的Q6和Q7控制,從上一章內容可知操控這片573芯片的方式,在看到 繼電器和蜂鳴器 另一端都是接的電源,也就是當out6和out7輸出高電平“1”時才能使這兩個元件停止工作,繼電器端并聯(lián)的二極管為續(xù)流二極管用來保護元件不被感應電壓擊穿或燒壞。

消音、關閉繼電器代碼如下:
  1. #include “stc15f2k60s2.h”

  2. void main()//消音、關閉繼電器程序
  3. {
  4.    while(1)
  5.    {
  6.    P2 = ((P2&0x1f)|0xA0); //選中控制蜂鳴器、繼電器的573芯片
  7.    P0 = 0X00; //輸入0000 0000,通過ULN2003取非,輸出1111 1111,
  8.    //使受控源兩端電勢差為0
  9.    }
  10. }
復制代碼

工程文件文末下載

  • 三、流水燈的兩種寫法
在這里為大家介紹兩種流水燈的寫法,也是單片機入門最簡單的一個程序,分別使用位運算的左右移符號“<<”、“>>”符號和調用左右移函數(shù)“_crol_”、“_cror_”兩種操作方式,原理介紹見代碼注釋,其中我們需要一個500毫秒的軟件延時函數(shù)可以直接使用我第一篇文章中介紹的方法直接用軟件生成。
流水燈①代碼如下:
  1. #include “stc15f2k60s2.h”
  2. #include “intrins.h”//因為延時函數(shù)中含有_nop_指令,
  3.                     //需要用到這個頭文件,同時流水燈2
  4.                     //中的左右移函數(shù)也是從中調用的

  5. void main()//流水燈1程序
  6. {
  7.    unsigned char i;

  8.    P2 = ((P2&0x1f)|0xA0);
  9.    P0 = 0X00; //先進行消音處理,蜂鳴器聲音刺耳。
  10.    P2 = ((P2&0x1f)|0x80);//選擇控制LED的573
  11.    P0 = 0x00;//點亮八個LED

  12.    while(1)//循環(huán)條件永遠為真,以下程序一直執(zhí)行下去。
  13.    {
  14.       for(i = 0; i < 8; i++)
復制代碼


流水燈②代碼如下
  1. <span style="font-family: Tahoma, &quot;Microsoft Yahei&quot;, Simsun;">#include</span><span style="font-family: Tahoma, &quot;Microsoft Yahei&quot;, Simsun;"> </span><span style="font-family: Tahoma, &quot;Microsoft Yahei&quot;, Simsun; white-space: normal;">“stc15f2k60s2.h”</span>
復制代碼
以上代碼中的Delay500ms();均是為了使led亮的時間能夠讓人用肉眼識別。

本章關于消音、點亮LED和流水燈的編程的介紹到此就大致結束了,下一章將開始講解獨立按鍵和矩陣鍵盤的程序編寫。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak's blog  http://www.bkoak.com/2018/02/13/lanqiao4/

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073



消音、點亮LED例程.rar

23.75 KB, 下載次數(shù): 10, 下載積分: 黑幣 -5

本章例程

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-14 10:19 來自手機 | 顯示全部樓層
本帖所有例程,博客原文中均可直接下載,沒有黑幣的朋友可以去原文下載
回復

使用道具 舉報

ID:274729 發(fā)表于 2018-2-14 10:52 | 顯示全部樓層
謝謝樓主
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-14 13:56 | 顯示全部樓層
本帖是不限于藍橋杯,主要針對單片機入門問題進行講解,有問題的朋友可以直接留言
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-14 17:20 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(5)獨立按鍵和矩陣鍵盤的應用

本章我們的主要內容分為兩部分
①  獨立按鍵的編程及使用
②  矩陣按鍵的掃描方式以及編程原理
PS:因為比賽使用的是IAP15的轉接板,該開發(fā)板不可使用按鍵處罰外部中斷的方式檢測按鍵,故不做討論,
同時IAP15芯片的WR/RD功能不是P36/P37引腳功能,故用P42/P44引腳代替
故提供兩種程序開頭寫法:
第一種使用reg52.h開頭的程序
  1. #include “stc15f2k60s2.h”

  2. void main()//消音、關閉繼電器程序
  3. {
  4.    while(1)
  5.    {
  6.       P2 = ((P2&0x1f)|0xA0); //選中控制蜂鳴器、繼電器的573芯片
  7.       P0 = 0X00; //輸入0000 0000,通過ULN2003取非,輸出1111 1111,
  8.       //使受控源兩端電勢差為0
  9.    }
  10. }
復制代碼



第二種使用stc15f2k60s2.h開頭的程序
  1. #include “stc15f2k60s2.h”//該文件已定義P4寄存器故下方無需重復定義

  2. sbit P3_6 = P4^2;//位定義用 P3_6 在程序中替換 P4^2的功能
  3. sbit P3_7 = P4^4;//同上
復制代碼


本文均以stc15為開頭的程序做示例。
  • 1ms延時程序(11.0592M晶振
  1. void Delay_1_ms(unsigned int n)//@11.0592MHz
  2. {
  3.    unsigned char i,j;
  4.    for(i = 0;i > n;i--)
  5.    {
  6.       _nop_();
  7.       _nop_();
  8.       _nop_();
  9.       i = 11;
  10.       j = 190;
  11.       do
  12.       {
  13.          while (--j);
  14.       } while (--i);
  15.    }
  16. }
復制代碼


該函數(shù)為后續(xù)例程中所使用的延時函數(shù)。

  • 獨立按鍵
首先,我們依然是先來看這一部分的電路原理圖
首先我們將左下角的端口選擇用跳線帽將2、3連在一起,我們可以看到按鍵S4~S7分別連接的是單片機的P30~P33端口,本章我們就用按鍵來控制上一章教學的LED不同的點亮方式來體現(xiàn)按鍵的功能。(為節(jié)約空間,此處僅以S7按鍵講解
示例程序:
  1. #include “stc15f2k60s2.h”
  2. #include “intrins.h”

  3. #define LED P0  //宏定義,在程序中可用LED代替P0使用

  4. sbit key0 = P3^0; //對S7按鍵所接端口進行位定義

  5. void Delay_1_ms(unsigned int n);

  6. void main()
  7. {
  8.    P2 = ((P2&0x1f)|0xA0); //不再重復解釋,前兩章已解釋多次
  9.    P0 = 0X00;
  10.    P2 = ((P2&0x1f)|0x80); //因為要使用LED故選擇到該區(qū)域
  11.    P0 = 0Xff;//先關閉LED
  12.       
  13.    while(1)
  14.    {
  15.    if(key0 == 0)//檔S7按鍵按下GND與P30導通P30得到低電平的信號
  16.       {
  17.          Delay_1_ms(10);//延時消抖,去除按鍵機械抖動帶來的干擾因素
  18.          if(key0 == 0)//再次確認按鍵按下
  19.          {
  20.             LED = 0X00;//按鍵按下 點亮所有LED
  21.             while(!key0);//判斷按鍵是否松開,如果為松開則停在此處等待
  22.          }
  23.          LED = 0xff;//按鍵松開,熄滅所有LED
  24.       }
  25.    }
  26. }
復制代碼



以上就是獨立按鍵的編程過程。
  • 矩陣鍵盤
現(xiàn)在我們將選擇端口,轉接到12上如原理圖所示,將按鍵分為四行四列,然后編程中我們分別進行“行”掃描和“列”掃描,進行標志位的標致,就能判斷出所按下的按鍵的是哪一個,詳細方法見一下程序。
掃描函數(shù)
  1. void keyscan()
  2. {
  3.    BUFFER = 0X0F; P3_6 = 0; P3_7 = 0;
  4.    /*首先我們進行列掃描,將P34~P37都置零,其中要注意,開發(fā)板上用
  5.    P42、P44替換了P36、P37故我們要單獨將這兩個IO置零*/
  6.    if(BUFFER != 0X0F)// “!=”表示檔P3不等于0x0f時條件為真
  7.    {
  8.       Delay_1_ms(10); //延時消抖
  9.       if(BUFFER != 0X0F)//再次判斷
  10.       {
  11.          switch(BUFFER)
  12.          /*當按鍵按下行中值發(fā)生變化得到一個BUFFER,
  13.          生成一個新的標志位*/
  14.          {
  15.             case 0X07: key_value = 1; break;
  16.             case 0X0B: key_value = 5; break;
  17.             case 0X0D: key_value = 9; break;
  18.             case 0X0E: key_value = 13; break;
  19.          }

  20.          BUFFER = 0XF0; P3_6 = 1; P3_7 = 1;
  21.          /*我們在進行行掃描,原理同上下方進行判斷第幾行
  22.          按鍵按下,結合列標志位生成新的行列標志位。*/
  23.          if(P3_7 == 0) key_value += 0; while(P3_7 == 0);
  24.          if(P3_6 == 0) key_value += 1; while(P3_6 == 0);
  25.          if(BUFFER == 0XD0) key_value += 2; while(BUFFER == 0XD0);
  26.          if(BUFFER == 0XE0) key_value += 3; while(BUFFER == 0XE0);
  27.       }
  28.    }
  29. }
復制代碼



主函數(shù)
  1. #include “stc15f2k60s2.h”
  2. #include “intrins.h”

  3. #define LED P0  //宏定義,在程序中可用LED代替P0使用
  4. #define BUFFER P3  //宏定義,在程序中用BUFFER代替P3端口

  5. sbit P3_6 = P4^2;//位定義用 P3_6 在程序中替換 P4^2的功能
  6. sbit P3_7 = P4^4;//同上

  7. void Delay_1_ms(unsigned int n);
  8. void keyscan();//鍵盤掃描函數(shù)

  9. void main()
  10. {
  11.    P2 = ((P20x1f)|0xA0); //不再重復解釋,前兩章已解釋多次
  12.    P0 = 0X00;
  13.    P2 = ((P20x1f)|0x80); //因為要使用LED故選擇到該區(qū)域
  14.    P0 = 0Xff;//先關閉LED
  15.       
  16.    while(1)
  17.    {
  18.       keyscan();//鍵盤掃描函數(shù)
  19.       switch(key_value)
  20.       {
  21.          case  1: LED = 0x00; break;
  22.          case  2: LED = 0x12; break;
  23.          case  3: LED = 0xab; break;
  24.          case  4: LED = 0xfe; break;
  25.          case  5: LED = 0x08; break;
  26.          case  6: LED = 0x0c; break;
  27.          case  7: LED = 0xa5; break;
  28.          case  8: ; break;
  29.          case  9: ; break;
  30.          case 10: ; break;
  31.          case 11: ; break;
  32.          case 12: ; break;
  33.          case 13: ; break;
  34.          case 14: ; break;
  35.          case 15: ; break;
  36.          case 16: ; break;//只定義了一部分按鍵功能,其余大家可以隨意發(fā)揮
  37.          case 17: ; break;//功能不限于點燈
  38.       }
  39.    }
  40. }
復制代碼



這些就是關于按鍵部分的內容部,最后再給大家留一道練習題,用以熟練按鍵的編程操作。
習題:用四個獨立按鍵和八個LED做一個八位二進制加法器,一個按鍵表示“+1”,一個按鍵表示“-1”,一個按鍵表示“清零”,一個按鍵表示“清零前最后一次顯示的數(shù)”。
如若黑幣不足可前往原文地址下載
本章關于獨立按鍵和矩陣鍵盤的編程的介紹到此就大致結束了,下一章將開始講解定時器0和動態(tài)數(shù)碼管的程序編程序。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak's blog  http://www.bkoak.com/2018/02/14/lanqiao5/

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073

獨立按鍵、矩陣鍵盤.rar

27.92 KB, 下載次數(shù): 10, 下載積分: 黑幣 -5

例程

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-14 21:27 | 顯示全部樓層
內個,第五篇通過下啊,下午就更新了的
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-15 13:21 來自手機 | 顯示全部樓層
今年過年,可能停更一天
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-16 01:51 | 顯示全部樓層
本章我們的主要內就只有一個,基本屬于純概念性問題,講解中斷系統(tǒng)的工作原理,看過留個映像,每次用到的時候在翻出來結合理解,多幾次就明白了,不求甚解為最佳。(重中之重)
在此做一個解釋說明,本來是想在第六章安排,靜態(tài)數(shù)碼管以及定時器的應用,但是我寫到定時器,發(fā)現(xiàn)內容量很大,在寫了一半定時器后又覺得不得不先為大家引入中斷系統(tǒng)這個概念,只有有了這個概念才能更好的理解運用定時器,故本章內容改為講解中斷系統(tǒng)的工作原理。
本章內容比較多,希望大家多結合手中資料進行自我學習,尤其是定時器部分一定要自己在好好看看datasheet,藍橋杯教學系列第一章內有下載地址。
  • 中斷系統(tǒng)
1)中斷的概念:這是大家需要在腦子里有的一個印象,我們大致可以將中斷描述成CPU在處理某一事件A時,發(fā)生了另一事件B請求CPU迅速去處理(中斷發(fā)生);CPU暫時中斷當前的工作,轉去處理事件B(中斷響應和中斷服務);待CPU將事件B處理完畢后,再回到原來事件A被中斷的地方繼續(xù)處理事件A(中斷返回),這一過程我們稱為中斷。
2)中斷源:我們將引起CPU中斷的根源或原因,稱為中斷源。中斷源向CPU提出的處理請求,稱為中斷請求或中斷申請。(傳統(tǒng)的51單片機有5個中斷源,而我們使用的IAP15有14個中斷源)
3)使用中斷我們一定要知道中斷優(yōu)先級和中斷嵌套這兩個概念。
①中斷優(yōu)先級:當有幾個中斷源同時申請中斷時,那么就存在CPU先響應哪個中斷請求的問題?為此,CPU要對各中斷源確定一個優(yōu)先等級,稱為中斷優(yōu)先級。中斷優(yōu)先級高的中斷請求優(yōu)先響應。
②中斷嵌套:中斷優(yōu)先級高的中斷請求可以中斷CPU正在處理的優(yōu)先級更低的中斷服務程序,待完成了中斷優(yōu)先權高的中斷服務程序之后,再繼續(xù)執(zhí)行被打斷的優(yōu)先級低的中斷服務程序,這就是中斷嵌套。
下圖為中斷系統(tǒng)的一個流程演示:
我們使用的IAP15F2K61S2單片機的中斷系統(tǒng)有14個中斷源,2個優(yōu)先級,可實現(xiàn)二級中斷服務嵌套。由片內特殊功能寄存器中的中斷允許寄存器IE、IE2、INT_CLKO控制CPU是否響應中斷請求;由中斷優(yōu)先級寄存器IP、IIP2安排各中斷源的優(yōu)先級;同一優(yōu)先級內2個以上中斷同時提出中斷請求時,由內部的查詢邏輯確定其響應次序。
中斷請求標志:IAP15F2K61S2單片機的10個中斷源的中斷請求標志分別寄存在TCON、SCON、PCON、S2CON、ADC_CONTR、SPSTAT、CCON中,其中,外部中斷2(/INT2)、外部中斷3(/INT3)和外部中斷4(/INT4)的中斷請求標志位被隱藏起來了,對用戶是不可見的。當相應的中斷被響應后或(EXn)=0(n=2、3、4),這些中斷請求標志位會自動被清0;定時器T2的中斷請求標志位也被隱藏起來了,對用戶是不可見的,當T2的中斷被響應后或(ET2)=0,這些中斷請求標志位會自動被清0。
IAP15F2K61S2單片機的中斷請求
中斷允許的控制:計算機中斷系統(tǒng)有兩種不同類型的中斷:一類稱為非屏蔽中斷,另一類稱為可屏蔽中斷。IAP15F2K61S2單片機的14個中斷源都是可屏蔽中斷,其中斷系統(tǒng)內部設有3個專用寄存器(IE、IE2、INT_CLKO)用于控制CPU對各中斷源的開放或屏蔽。
中斷優(yōu)先的控制:IAP15F2K61S2單片機除外部中斷2(/INT2)、外部中斷3(/INT3)、定時器T2中斷和外部中斷4(/INT4)為固定最低優(yōu)先級中斷外,其他中斷都具有2個中斷優(yōu)先級,可實現(xiàn)二級中斷服務嵌套。IP、IP2為中斷優(yōu)先級寄存器,鎖存各中斷源優(yōu)先級控制位。
自然優(yōu)先級排序
中斷源                                                       同級自然優(yōu)先順序
外部中斷0                                                  最高
定時器T0
中斷
外部中斷1
定時器T1中斷
串行口中斷
A/D轉換中斷
LVD中斷
PCA中斷
串行口2中斷
SPI中斷
外部中斷2
外部中斷3
定時器T2中斷
外部中斷4                                                    最低
IAP15F2K61S2單片機中斷響應
中斷響應:是CPU對中斷源中斷請求的響應,包括保護斷點和將程序轉向中斷服務程序的入口地址(通常稱矢量地址)。CPU并非任何時刻都響應中斷請求,而是在中斷響應條件滿足之后才會響應。
中斷服務與中斷返回:中斷服務與中斷返回就是通過執(zhí)行中斷服務程序完成的。中斷服務程序從中斷入口地址開始執(zhí)行,到返回指令“RETI”為止,一般包括四部分內容,其結構是:保護現(xiàn)場,中斷服務,恢復現(xiàn)場、中斷返回。
保護現(xiàn)場:用入棧操作指令將需保護寄存器的內容壓入堆棧。
中斷服務:中斷服務程序的核心部分,是中斷源中斷請求之所在。
恢復現(xiàn)場:在中斷服務結束之后,中斷返回之前,用出棧操作指令將保護現(xiàn)場中壓入堆棧的內容彈回到相應的寄存器中,注意彈出順序必須與壓入順序相反。
中斷返回:中斷返回是指中斷服務完成后,計算機返回原來斷開的位置(即斷點),繼續(xù)執(zhí)行原來的程序。中斷返回由中斷返回指令RETI來實現(xiàn)。

本章無需要下載文件,請各位自行查閱第一章下載資料中的STC15.pdf文檔。

本章知識點雜且多,文章中我也無法做到全面覆蓋,像定時器中斷、PCA中斷和外部中斷有很多的運用方法,文中并沒有一一舉例,只是從概念和我們使用的單片機的結構上簡單的介紹了中斷系統(tǒng)的概念,還需要大家多復習自己多去看看多去想想,在實踐中理解運用,將書面中的東西化作自己腦海中的東西。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak's blog[url]http://www.bkoak.com/2018/02/12/lanqiao3/[/url]

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-16 21:50 | 顯示全部樓層
本章我們的主要內容也只有一個,同樣基本屬于純概念性問題,講解定時器/計數(shù)器(Timer0/1)的功能模式和使用原理,這部分內容如果單純只看是比較難理解的,希望大家結合前幾張的內容來自己試著改寫一下以前的程序,將之前程序中的延時程序用定時器來做替換完成同樣的功能。
定時器(Timer0/1)
首先我們需要知道定時器Timer需要使用的寄存器有哪些:
我們先來簡單的說一下TMOD、 TCON兩個寄存器的功能和區(qū)別:
1)TMOD:就是運行模式配置寄存器,也就是配置定時器是工作在定時器狀態(tài)還是計數(shù)器狀態(tài),以及定時器的工作模式是13位定時器,16位定時器,雙8位定時器自動重裝,還是雙8位定時器等等。
2)TCON:就是定時/計數(shù)器的控制寄存器,包括控制定時器的的啟動與停止,是否允許外部的中斷請求判斷定時器是否已經溢出等等。
簡而言之,一句話2個寄存器 一個是配置模式功能 一個是控制功能,具體的運用理解還需要大家多看多用。
定時器/計數(shù)器0/1控制寄存器TCON
TCON為定時器/計數(shù)器T0、T1的控制寄存器,同時也鎖存T0、T1溢出中斷源和外部請求中斷源等,TCON格式如下:
TCON為定時器/計數(shù)器中斷控制寄存器(可位尋址)
各寄存器功能請見datasheet P592。
定時器/計數(shù)器0/1工作模式寄存器TMOD
定時和計數(shù)功能由特殊功能寄存器TMOD的控制位C/T進行選擇,TMOD寄存器的各位信息。
可以看出,2個定時/計數(shù)器有4鐘操作模式,通過TMOD的M1和M0選擇。2個定時/計數(shù)器模式0、1和2都相同,模式3不同,各模式下的功能請參見datasheet P593。
定時器0/1的中斷控制寄存器:IE和IP
IE:中斷允許寄存器(可位尋址)
EA:CPU的總中斷允許控制位,EA = 1,CPU開放中斷,EA = 0,CPU屏蔽所有的中斷申請。
ET1:定時/計數(shù)器T1的溢出中斷允許位,ET1 = 1,允許T1中斷,ET1 = 0禁止T1中斷。
ET0:同上。
IP:中斷優(yōu)先級控制寄存器(可位尋址)
PT1:           定時器1中斷優(yōu)先級控制位。
當PT1 = 0時,定時器1中斷為最低優(yōu)先級中斷(優(yōu)先級0)
當PT1 = 1時,定時器1中斷為最高優(yōu)先級中斷(優(yōu)先級1)
PT0:           定時器1中斷優(yōu)先級控制位。
當PT0 = 0時,定時器0中斷為最低優(yōu)先級中斷(優(yōu)先級0)
當PT0 = 1時,定時器0中斷為最高優(yōu)先級中斷(優(yōu)先級1)
注意事項詳見datasheet P597。
輔助寄存器AUXR
普通8051單片機是12T的機器周期,STC15的是1T的這個輔助寄存器的功能就是用來選擇STC15工作在1T還是12T的模式下。
定時器/計數(shù)器0工作模式
通過對寄存器TMOD中的M1(TMOD.1)、(TMOD.0)的設置,定時器/計數(shù)器0有4種不同的工作模式。
模式0(16位自動重裝載模式)(只介紹該模式,其余三種模式見datasheet
定時器/計數(shù)器0工作模式0(16位自動重裝載模式)
M1和M0:方式選擇控制位
C/ T:功能選擇位。
1:計數(shù)器功能(對T0或T1引腳的負跳變進行計數(shù))。
0:定時器功能(對時鐘周期進行計數(shù))。
GATE:門控位。GATE用于選通控制。
1:INTX為高電平且TRX置位時,啟動定時器工作。
0:每當TRX置位時,就啟動定時器工作。
注意:TMOD寄存器不能進行位尋址,設置時只 能對整個寄存器賦值。
IAP15F2K61S2的定時器有兩種計數(shù)速率:一種是12T模式,每12個時鐘加1;另一種是1T模式,每個時鐘加1。
T0和T1的速率分別由特殊功能寄存器AUXR中的T0x12和T1x12決定。
T0x12=0,T0工作在12T模式;
T0x12=1,T0工作在1T模式。
T1x12=0,T1工作在12T模式;
T1x12=1,T1則工作在1T模式。
定時器0和定時器1分別有2個隱藏的寄存器RL_THx和RL_TLx。RL_THx與THx共有同一個地址,RL_TLx與TLx共有同一個地址。當TRx=0即定時器/計數(shù)器被禁止工作時,對TLx、THx寫入的內容會同時寫入RL_TLx、RL_THx。 當TRx=1即定時器/計數(shù)器工作時,對TLx 、THx寫入的內容不會寫入RL_TLx 、RL_THx。
當定時器工作在模式0時,[TLx,THx]的溢出 不僅置位TFx,而且會自動將[RL_TLx,RL_THx] 的內容重新裝入[TLx,THx]。
當T0CLKO=1時,T1/P3.5引腳配置為定時器0的時鐘輸出CLKOUT0。
當T1CLKO=1時,T0/P3.4引腳配置為定時器1的時鐘輸出CLKOUT1。
詳細介紹參見datasheet P600。
定時器的最大定時能力
當工作于定時狀態(tài)時,定時/計數(shù)器是對時鐘周期進行計數(shù),若對時鐘進行12分頻,則對每12個時鐘周期計數(shù)一次。
當晶振頻率為6MHz,采用12分頻時,計數(shù)的單位時間為:
單位時間為:
定時時間為:   TC=XTu。
其中,Tu為單位時間,TC為定時時間,X為所需計數(shù)次數(shù)。
STC15F2K60S2單片機的定時/計數(shù)器是加1計數(shù)器。因此,不能直接將實際的計數(shù)值作為計數(shù)初值送入計數(shù)寄存器THX、TLX中,而必須將實際計數(shù)值以28、216為模求補,以補碼作為計數(shù)初值設置THX和TLX。
即應裝入計數(shù)/定時器的初值為:,其中,n=8或16。
例如:已知Tu=2μs,要求定時TC=1ms,則
  • 對方式0和方式1,時間常數(shù)為:216-500=65036=FE0CH (THX裝入FEH,TLX裝入0CH)。
設系統(tǒng)時鐘頻率為6MHz,12分頻時,
  • 8位定時器的最大定時能力為:T=(28 -0)×2μs=512μs
  • 16位定時器的最大定時能力為:T=(216 -0)×2μs=131072μs=131.072ms
最后補充一下,初學階段對定時器的使用可以直接使用我第一章中所講的方法直接自動生成所需定時器,用以程序使用,但是還是希望大家理解最重要。
以上是定時器的原理,接下來我們簡單運用定時器來寫個控制LED量滅的程序:
  1. #include “stc15f2k60s2.h”

  2. #define LED P0

  3. unsigned char t;

  4. void Timer0Init(void);

  5. void main()
  6. {
  7.    P2 = ((P2&0x1f)|0xA0); //不再重復解釋,前兩章已解釋多次
  8.    P0 = 0X00;
  9.    P2 = ((P2&0x1f)|0x80);
  10.    P0 = 0Xff;//先關閉LED

  11.    Timer0Init();
  12.    EA = 1; //打開定時器0
  13.    ET0 = 1;

  14.    while(1)
  15.    {
  16.       if(t == 200)
  17.       {
  18.          LED = ~LED;
  19.          t = 0;//初始化標志位
  20.       }
  21.    }
  22. }

  23. void Timer0Init(void)//5毫秒@11.0592MHz
  24. {
  25.    AUXR |= 0x80;//定時器時鐘1T模式
  26.    TMOD &= 0xF0;//設置定時器模式
  27.    TL0 = 0x00;//設置定時初值
  28.    TH0 = 0x28;//設置定時初值
  29.    TF0 = 0;//清除TF0標志
  30.    TR0 = 1;//定時器0開始計時
  31. }

  32. void Timer0() interrupt 1 //定時器0的開啟中斷1
  33. {
  34.    t++;
  35. }
復制代碼



               本章資料下載地址請前往原址。
本章關于定時器的講解就到此結束了,希望大家多在實踐中學習,多用多看,一邊動手一邊學習,加強自己對知識點的理解。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak's blog  http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073


回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-17 19:31 | 顯示全部樓層
鄭重聲明,請不要復制粘貼代碼,第一可能會被網頁專制標點符號,導致編譯報錯,其次復制粘貼達成的效果,可能會讓你產生一種我會了的錯覺。
本章我們的主要內容是靜態(tài)數(shù)碼管和動態(tài)數(shù)碼管的編程,主要內容在程序中講解,同時會復習一下上一章定時器的內容。
共陰/共陽數(shù)碼管
首先我們先來了解一下數(shù)碼管的工作原理,我們普遍將數(shù)碼管分為兩種一種是共陰數(shù)碼管一種是共陽數(shù)碼管(我們使用的是兩個4位八段共陽數(shù)碼管)。
所謂八段數(shù)碼管就是八個發(fā)光二極管組成的如上圖的結構形態(tài),共陰數(shù)碼管就是八個LED陰極相連組成公共端接GND,共陽數(shù)碼管就是八個LED陽極相連組成公共端接VCC。
我們使用的4位八段數(shù)碼驅動原理也是如此其中八個管腳作為(A,B,C,D,E,F,G,DP)的驅動端口,選擇哪一段數(shù)碼管亮或不亮,我們稱之為數(shù)碼管段選,還有4個管腳作為選擇四位數(shù)碼管中的哪一位亮或不亮的驅動端口,也就是四個公共端,我們稱之為數(shù)碼管位選。
驅動原理
下面我們來看一下我們開發(fā)板的驅動原理圖是如何驅動這兩個四位共陽數(shù)碼管的。
圖中a1、b1……dp1就是數(shù)碼管的段選端口,com1、com2……com8就是數(shù)碼管的位選端口,我們可以看到,藍橋杯開發(fā)板的數(shù)碼管段選和位選都是通過單片機的P0寄存器來驅動的,但是因為P0不能同一時刻既做段選又做位選,所以這里就要通過我們第二章所講的內容來操作在一個很短的時間內在段選和位選之間切換選擇操作。
靜態(tài)數(shù)碼管數(shù)碼管所有公共端接GND或VCC,在該開發(fā)板上不是接GND和VCC而是接在兩個573三態(tài)鎖存器上,全亮全滅不單獨選擇端口操作。優(yōu)點:不閃爍,亮度高。缺點:占用端口多。
示例程序:
[backcolor=rgb(15, 25, 42) !important][size=1em]
[size=1em]01

[size=1em]02

[size=1em]03

[size=1em]04

[size=1em]05

[size=1em]06

[size=1em]07

[size=1em]08

[size=1em]09

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em]48

[size=1em]49

[size=1em]50

[size=1em]51

[size=1em]52

[size=1em]53

[size=1em]54

[size=1em]55

[size=1em]56

[size=1em]57

[size=1em][size=1em]/******************/
[size=1em] /* 2018.2.17 */
[size=1em] /* www.bkoak.com */
[size=1em] /* 數(shù)碼管程序示例 */
[size=1em] /******************/
[size=1em]#include “stc15f2k60s2.h”
[size=1em]#define uchar unsigned char
[size=1em]#define uint unsigned int

[size=1em]uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
[size=1em]                  0x82,0xf8,0x80,0x90,0xbf,0xff};
[size=1em]/*這里如果不加code,就會占用寄存器,允許讀取和修改寄存器的值,
[size=1em]但是寄存器的數(shù)量有限,故我們在這里加上code,將其定義為代碼的
[size=1em]類型,只能讀取不能修改*/
[size=1em]uchar t = 0,i;

[size=1em]void Timer0Init(void);

[size=1em]void main()
[size=1em]{
[size=1em]   P2 = ((P2&0x1f)|0xa0);//不再重復解釋,前兩章已解釋多次
[size=1em]   P0 = 0x00;
[size=1em]   P2 = ((P2&0x1f)|0xc0);//打開位選選573
[size=1em]   P0 = 0xff;//選擇8位數(shù)碼管
[size=1em]   P2 = ((P2&amp;0x1f)|0xff);//打開段選573

[size=1em]   Timer0Init();
[size=1em]   EA=1;
[size=1em]   ET0=1;

[size=1em]   while(1)
[size=1em]   {
[size=1em]      if(t == 100)
[size=1em]      {
[size=1em]         t = 0;
[size=1em]         P0 = tab;
[size=1em]         i++;
[size=1em]         if(i == 12)
[size=1em]            i = 0;
[size=1em]      }
[size=1em]   }
[size=1em]}

[size=1em]void Timer0Init(void)//5毫秒@11.0592MHz
[size=1em]{
[size=1em]   AUXR |= 0x80;//定時器時鐘1T模式
[size=1em]   TMOD &= 0xF0;//設置定時器模式
[size=1em]   TL0 = 0x00;//設置定時初值
[size=1em]   TH0 = 0x28;//設置定時初值
[size=1em]   TF0 = 0;//清除TF0標志
[size=1em]   TR0 = 1;//定時器0開始計時
[size=1em]}

[size=1em]void Timer0() interrupt 1
[size=1em]{
[size=1em]   t++;
[size=1em]}



動態(tài)數(shù)碼管數(shù)碼管公共端依次掃描接通。優(yōu)點:占用端口少。缺點:攝像,拍照時閃爍,在同樣電壓下與靜態(tài)相比,亮度較低。[backcolor=rgb(15, 25, 42) !important][size=1em]
[size=1em]01

[size=1em]02

[size=1em]03

[size=1em]04

[size=1em]05

[size=1em]06

[size=1em]07

[size=1em]08

[size=1em]09

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em]48

[size=1em]49

[size=1em]50

[size=1em]51

[size=1em]52

[size=1em]53

[size=1em]54

[size=1em]55

[size=1em]56

[size=1em]57

[size=1em]58

[size=1em]59

[size=1em]60

[size=1em]61

[size=1em]62

[size=1em]63

[size=1em]64

[size=1em]65

[size=1em]66

[size=1em]67

[size=1em]68

[size=1em]69

[size=1em][size=1em]#include "stc15f2k60s2.h"
[size=1em]#include "intrins.h"

[size=1em]#define uchar unsigned char
[size=1em]#define uint unsigned int

[size=1em]uchar code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,
[size=1em]                    0x82,0xf8,0x80,0x90,0xbf,0x7f};
[size=1em]/*這里如果不加code,就會占用寄存器,允許讀取和修改寄存器的值,
[size=1em]但是寄存器的數(shù)量有限,故我們在這里加上code,將其定義為代碼的
[size=1em]類型,只能讀取不能修改*/
[size=1em]uchar t = 0;
[size=1em]uchar c5, c6, c7, c8;
[size=1em]uint num = 2330;

[size=1em]void Timer0Init(void);
[size=1em]void display(uchar c5, uchar c6, uchar c7, uchar c8);
[size=1em]void Delay1ms();

[size=1em]void main()
[size=1em]{
[size=1em]   P2 = ((P2&amp;0x1f)|0xa0);//不再重復解釋,前兩章已解釋多次
[size=1em]   P0 = 0x00;
[size=1em]   
[size=1em]   Timer0Init();
[size=1em]   EA=1;
[size=1em]   ET0=1;
[size=1em]   
[size=1em]   while(1)
[size=1em]   {
[size=1em]      if(t == 200)
[size=1em]      {
[size=1em]         t = 0;
[size=1em]         num--;
[size=1em]         c5 = (num / 1000) % 10;
[size=1em]         c6 = (num / 100) % 10;
[size=1em]         c7 = (num /10) % 10;
[size=1em]         c8 = num % 10;
[size=1em]      }
[size=1em]      display(c5, c6, c7, c8);
[size=1em]   }
[size=1em]}

[size=1em]void display(uchar c5, uchar c6, uchar c7, uchar c8)
[size=1em]{
[size=1em]   P2 = ((P2&0x1f)|0xc0);
[size=1em]   P0 = 0x80;
[size=1em]   P2 = ((P2&0x1f)|0xff);
[size=1em]   P0 = tab[c8];
[size=1em]   Delay1ms();

[size=1em]   P2 = ((P2&0x1f)|0xc0);
[size=1em]   P0 = 0x40;
[size=1em]   P2 = ((P2&0x1f)|0xff);
[size=1em]   P0 = tab[c7];
[size=1em]   Delay1ms();

[size=1em]   P2 = ((P2&0x1f)|0xc0);
[size=1em]   P0 = 0x20;
[size=1em]   P2 = ((P2&0x1f)|0xff);
[size=1em]   P0 = tab[c5];
[size=1em]   Delay1ms();

[size=1em]   P2 = ((P2&0x1f)|0xc0);
[size=1em]   P0 = 0x10;
[size=1em]   P2 = ((P2&0x1f)|0xff);
[size=1em]   P0 = tab[c6];
[size=1em]   Delay1ms();
[size=1em]}



本章資料下載地址見原文。
本章的內容到這里就結束了,最后給大家留一個題目,可以回去思考,后面有時間也會更新講解,使用單片機定時器制作一個以00-00-00為初始可以通過四個獨立按鍵進行時間修改的24小時制時鐘。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-18 00:34 | 顯示全部樓層
上一貼直接復制原文可能導致網頁編碼出問題,程序顯示不正常萬望兩節(jié)

在此補發(fā)
【藍橋杯單片機設計與開發(fā)】(8)靜態(tài)數(shù)碼管/動態(tài)數(shù)碼管的編程作者: bkoak 分類: 藍橋杯 發(fā)布時間: 2018-02-17 19:19 編輯


鄭重聲明,請不要復制粘貼代碼,第一可能會被網頁專制標點符號,導致編譯報錯,其次復制粘貼達成的效果,可能會讓你產生一種我會了的錯覺。
本章我們的主要內容是靜態(tài)數(shù)碼管和動態(tài)數(shù)碼管的編程,主要內容在程序中講解,同時會復習一下上一章定時器的內容。
共陰/共陽數(shù)碼管
首先我們先來了解一下數(shù)碼管的工作原理,我們普遍將數(shù)碼管分為兩種一種是共陰數(shù)碼管一種是共陽數(shù)碼管(我們使用的是兩個4位八段共陽數(shù)碼管)。
所謂八段數(shù)碼管就是八個發(fā)光二極管組成的如上圖的結構形態(tài),共陰數(shù)碼管就是八個LED陰極相連組成公共端接GND,共陽數(shù)碼管就是八個LED陽極相連組成公共端接VCC。
我們使用的4位八段數(shù)碼驅動原理也是如此其中八個管腳作為(A,B,C,D,E,F,G,DP)的驅動端口,選擇哪一段數(shù)碼管亮或不亮,我們稱之為數(shù)碼管段選,還有4個管腳作為選擇四位數(shù)碼管中的哪一位亮或不亮的驅動端口,也就是四個公共端,我們稱之為數(shù)碼管位選。
驅動原理
下面我們來看一下我們開發(fā)板的驅動原理圖是如何驅動這兩個四位共陽數(shù)碼管的。
圖中a1、b1……dp1就是數(shù)碼管的段選端口,com1、com2……com8就是數(shù)碼管的位選端口,我們可以看到,藍橋杯開發(fā)板的數(shù)碼管段選和位選都是通過單片機的P0寄存器來驅動的,但是因為P0不能同一時刻既做段選又做位選,所以這里就要通過我們第二章所講的內容來操作在一個很短的時間內在段選和位選之間切換選擇操作。
靜態(tài)數(shù)碼管數(shù)碼管所有公共端接GND或VCC,在該開發(fā)板上不是接GND和VCC而是接在兩個573三態(tài)鎖存器上,全亮全滅不單獨選擇端口操作。優(yōu)點:不閃爍,亮度高。缺點:占用端口多。
示例程序:
  1. /******************/
  2. /* 2018.2.17 */
  3. /* www.bkoak.com */
  4. /* 數(shù)碼管程序示例 */
  5. /******************/
  6. #include “stc15f2k60s2.h”
  7. #define uchar unsigned char
  8. #define uint unsigned int

  9. uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
  10.                   0x82,0xf8,0x80,0x90,0xbf,0xff};
  11. /*這里如果不加code,就會占用寄存器,允許讀取和修改寄存器的值,
  12. 但是寄存器的數(shù)量有限,故我們在這里加上code,將其定義為代碼的
  13. 類型,只能讀取不能修改*/
  14. uchar t = 0,i;

  15. void Timer0Init(void);

  16. void main()
  17. {
  18.    P2 = ((P2&0x1f)|0xa0);//不再重復解釋,前兩章已解釋多次
  19.    P0 = 0x00;
  20.    P2 = ((P2&0x1f)|0xc0);//打開位選選573
  21.    P0 = 0xff;//選擇8位數(shù)碼管
  22.    P2 = ((P2&0x1f)|0xff);//打開段選573

  23.    Timer0Init();
  24.    EA=1;
  25.    ET0=1;

  26.    while(1)
  27.    {
  28.       if(t == 100)
  29.       {
  30.          t = 0;
  31.          P0 = tab[i];
  32.          i++;
  33.          if(i == 12)
  34.             i = 0;
  35.       }
  36.    }
  37. }

  38. void Timer0Init(void)//5毫秒@11.0592MHz
  39. {
  40.    AUXR |= 0x80;//定時器時鐘1T模式
  41.    TMOD &= 0xF0;//設置定時器模式
  42.    TL0 = 0x00;//設置定時初值
  43.    TH0 = 0x28;//設置定時初值
  44.    TF0 = 0;//清除TF0標志
  45.    TR0 = 1;//定時器0開始計時
  46. }

  47. void Timer0() interrupt 1
  48. {
  49.    t++;
  50. }
復制代碼

動態(tài)數(shù)碼管數(shù)碼管公共端依次掃描接通。優(yōu)點:占用端口少。缺點:攝像,拍照時閃爍,在同樣電壓下與靜態(tài)相比,亮度較低。示例程序:
  1. #include "stc15f2k60s2.h"
  2. #include "intrins.h"

  3. #define uchar unsigned char
  4. #define uint unsigned int

  5. uchar code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,
  6.                     0x82,0xf8,0x80,0x90,0xbf,0x7f};
  7. /*這里如果不加code,就會占用寄存器,允許讀取和修改寄存器的值,
  8. 但是寄存器的數(shù)量有限,故我們在這里加上code,將其定義為代碼的
  9. 類型,只能讀取不能修改*/
  10. uchar t = 0;
  11. uchar c5, c6, c7, c8;
  12. uint num = 2330;

  13. void Timer0Init(void);
  14. void display(uchar c5, uchar c6, uchar c7, uchar c8);
  15. void Delay1ms();

  16. void main()
  17. {
  18.    P2 = ((P2&0x1f)|0xa0);//不再重復解釋,前兩章已解釋多次
  19.    P0 = 0x00;
  20.    
  21.    Timer0Init();
  22.    EA=1;
  23.    ET0=1;
  24.    
  25.    while(1)
  26.    {
  27.       if(t == 200)
  28.       {
  29.          t = 0;
  30.          num--;
  31.          c5 = (num / 1000) % 10;
  32.          c6 = (num / 100) % 10;
  33.          c7 = (num /10) % 10;
  34.          c8 = num % 10;
  35.       }
  36.       display(c5, c6, c7, c8);
  37.    }
  38. }

  39. void display(uchar c5, uchar c6, uchar c7, uchar c8)
  40. {
  41.    P2 = ((P2&0x1f)|0xc0);
  42.    P0 = 0x80;
  43.    P2 = ((P2&0x1f)|0xff);
  44.    P0 = tab[c8];
  45.    Delay1ms();

  46.    P2 = ((P2&0x1f)|0xc0);
  47.    P0 = 0x40;
  48.    P2 = ((P2&0x1f)|0xff);
  49.    P0 = tab[c7];
  50.    Delay1ms();

  51.    P2 = ((P2&0x1f)|0xc0);
  52.    P0 = 0x20;
  53.    P2 = ((P2&0x1f)|0xff);
  54.    P0 = tab[c5];
  55.    Delay1ms();

  56.    P2 = ((P2&0x1f)|0xc0);
  57.    P0 = 0x10;
  58.    P2 = ((P2&0x1f)|0xff);
  59.    P0 = tab[c6];
  60.    Delay1ms();
  61. }
復制代碼


無黑幣朋友下載地址可見原文處。
本章的內容到這里就結束了,最后給大家留一個題目,可以回去思考,后面有時間也會更新講解,使用單片機定時器制作一個以00-00-00為初始可以通過四個獨立按鍵進行時間修改的24小時制時鐘。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com
聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073



靜態(tài)數(shù)碼管、動態(tài)數(shù)碼管.rar

27.21 KB, 下載次數(shù): 8, 下載積分: 黑幣 -5

例程

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-18 18:13 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(9)定時器中斷實現(xiàn)實時時鐘程序作者: bkoak 分類: 藍橋杯 發(fā)布時間: 2018-02-18 18:10
本章的內容就是上一章結束后留給大家的思考題,使用單片機定時器制作一個以00-00-00模式顯示,可以通過四個獨立按鍵進行時間修改的24小時制時鐘。
在前面幾張已經為大家介紹了定時器、中斷、數(shù)碼管、按鍵等功能的使用方法,本章我們就將使用這些工能制作一個簡易的可調實時時鐘,自己寫不出可以抄代碼,但是不要用復制粘貼的方式去完成程序,這是在為自己學習,在位比賽做準備,比賽的時候沒有例程讓你復制。

示例程序:
  1. #include "stc15f2k60s2.h"

  2. #define uchar unsigned char
  3. #define uint unsigned

  4. sbit key1=P3^0;//定義端口參數(shù)
  5. sbit key2=P3^1;
  6. sbit key3=P3^2;
  7. sbit key4=P3^3;
  8. /*
  9. key1用于小時 +1
  10. key2用于小時 -1
  11. key3用于分鐘 +1
  12. key4用于分鐘 -1
  13. */

  14. int uchar code tab[] =
  15. {0xc0,0xf9,0xa4,0xb0,0x99,0x92,
  16. 0x82,0xf8,0x80,0x90,0xbf,0x7f};
  17. uchar strtab[8];//定義緩沖區(qū)域
  18. uchar hour = 10, minute = 25, second = 12;
  19. //初始化起始時間10-25-12

  20. void display(void);
  21. void delayms(int ms);
  22. void Timer0Init(void);
  23. void Timer1Init(void);

  24. void main()
  25. {
  26.    P2 = ((P2&0x1f)|0xa0);
  27.    P0 = 0x00;

  28.    Timer0Init();
  29.    Timer1Init();
  30.    ET0 = 1;//開啟定時器0
  31.    ET1 = 1;//同上
  32.    EA = 1;//定時器使能

  33.    display();
  34.    while(1)
  35.    {
  36.       if (!key1)
  37.       {
  38.          delayms(5);//按鍵消抖
  39.          if (!key1)
  40.          {
  41.             hour++;
  42.             if (hour == 24)
  43.                hour = 0;
  44.             display();
  45.             while(!key1);//松手檢測
  46.          }
  47.       }
  48.       //其余三個按鍵功能請自行編寫,如遇問題請下載參考源程序
  49.    }
  50. }

  51. void display(void)
  52. {
  53.    strtab[0] = tab[hour / 10];
  54.    strtab[1] = tab[hour % 10];
  55.    strtab[2] = tab[10];
  56.    strtab[3] = tab[minute % 10];
  57.    strtab[4] = tab[minute % 10];
  58.    strtab[5] = tab[10];
  59.    strtab[6] = tab[second / 10];
  60.    strtab[7] = tab[second % 10];
  61. }

  62. void delayms(int ms)
  63. {
  64.    int i,j;
  65.    for(i=ms;i>0;i--)
  66.       for(j=845;j>0;j--);
  67. }

  68. void Timer0Init(void) //5毫秒@11.0592MHz
  69. //內容請自行計算

  70. void Timer1Init(void) //1毫秒@11.0592MHz
  71. //內容請自行計算

  72. void Timer1_int() interrupt 3 using 0
  73. {
  74.    static uchar num;
  75.    TH1 = 0xcd;
  76.    TL1 = 0xd4;

  77.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  78.    {
  79.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x01;
  80.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  81.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x02;
  82.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  83.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x04;
  84.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  85.       case 3: P2 = ((P2&0x1f)|0xc0); P0 = 0x08;
  86.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  87.       case 4: P2 = ((P2&0x1f)|0xc0); P0 = 0x10;
  88.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  89.       case 5: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  90.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  91.       case 6: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  92.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  93.       case 7: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  94.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  95.       default:break;
  96.    }
  97.    num++;
  98.    if (num == 8)
  99.       num = 0;
  100. }
  101. void Timer0_int() interrupt 1 using 1
  102. {
  103.    static uchar count;//定義內部靜態(tài)變量
  104.    TL0 = 0x00; //初始化初值
  105.    TH0 = 0x28;<
  106.    count++;

  107.    switch (count);
  108.    {
  109.       case 0:
  110.       case 40:
  111.       case 80:
  112.       case 120:
  113.       case 160:display();break;
  114.    }
  115.    if (count == 200)
  116.    {
  117.       count = 0;
  118.       second++;//加一秒
  119.       if (second == 60)
  120.       {
  121.          second = 0;
  122.          minute++;//加一分
  123.          if (minute == 60)
  124.          {
  125.             minute = 0;
  126.             hour++;//加一小時
  127.             if (hour == 24)
  128.                hour = 0;
  129.          }
  130.       }
  131.    }
  132. }
復制代碼

本章資料下載若無黑幣可前往原網址下載。
本章的內容到這里就結束了,最后給大家留一個題目,可以回去思考,后面有時間也會更新講解,使用單片機定時器制作一個以00-00-00為初始可以通過四個獨立按鍵進行時間修改的24小時制時鐘。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com
聯(lián)系博主
郵箱:wjf418224424@aliyun.com
QQ交流群:693211073


定時器24小時時鐘.rar

21.52 KB, 下載次數(shù): 11, 下載積分: 黑幣 -5

例程

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-19 11:03 來自手機 | 顯示全部樓層
今天有事出門不更新教程了。晚點在博客更新一篇日記吧。
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-20 11:23 | 顯示全部樓層
晚上更新
大家可以下看下這個帖子
一點個人對電子之路的見解
http://www.torrancerestoration.com/bbs/dpj-107569-1.html
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-21 00:27 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(10)DS18B20原理講解及程序編寫(上)
  • DS18B20——可編程分辨率的單總線®數(shù)字溫度計
首先我們先看來看一下DS18B20的引腳說明:
GND  -   地
DQ     -   數(shù)據(jù) I/O
VDD  -   可選電源電壓
NC     -   無連接
*所有上表未提及的引腳都無連接。
我們再來看看DS18B20的基本特征:
① 獨特的單線接口僅需一個端口引腳進行通訊
② 每個器件有唯一的 64 位的序列號存儲在內部存儲器中
③ 簡單的多點分布式測溫應用
④ 無需外部器件
⑤ 可通過數(shù)據(jù)線供電。供電范圍為 3.0V到 5.5V
⑥ 測溫范圍為-55~+125℃(-67~+257℉)
⑦ 在-10~+85℃范圍內精確度為±5℃
⑧ 溫度計分辨率可以被使用者選擇為9~12 位
⑨ 最多在 750ms 內將溫度轉換為 12 位數(shù)字
⑩ 用戶可定義的非易失性溫度報警設置
⑪ 報警搜索命令識別并標志超過程序限定溫度(溫度報警條件)的器件
⑫ 與 DS1822 兼容的軟件
⑬ 應用包括溫度控制、工業(yè)系統(tǒng)、消費品、溫度計或任何熱感測系統(tǒng)
說明、概覽內容請自行參閱datasheet
① 64 位只讀存儲器儲存器件的唯一片序列號
② 高速暫存器含有兩個字節(jié)的溫度寄存器,這兩個寄存器用來存儲溫度傳感器輸出的數(shù)據(jù)
③ 高速暫存器提供一個直接的溫度報警值寄存器(TH 和 TL)
④ 控制線需要連接一個弱上拉電阻
測溫操作
當需要執(zhí)行溫度測量和 AD 轉換時,總線控制器必須發(fā)出[44h]命令。
溫度/ 數(shù)據(jù)關系
*上電復位時溫度寄存器默認值為+85℃
報警操作信號
當 TH 和 TL 為 8 位寄存器時,4 位溫度寄存器中的 11 個位用來和 TH、TL 進行比較。如果測得的溫度高于 TH 或低于 TL,報警條件成立,DS18B20 內部就會置位一個報警標識,總線控制器通過發(fā)出報警搜索命令[ECh]檢測總線上所有的 DS18B20 報警標識。
DS18B20 供電
DS18B20 可以通過從 VDD 引腳接入一個外部電源供電,或者可以工作于寄生電源模式,該模式允許 DS18B20 工作于無外部電源需求狀態(tài)。
當 DS18B20 處于寄生電源模式時,VDD 引腳必須接地。
在發(fā)出溫度轉換指令[44h]或拷貝暫存器指令[48h]之后,必須在至多 10us 之內把單總線轉換到強上拉,并且在溫度轉換時序(tconv)或拷貝數(shù)據(jù)時序(ter=10 ms)必須一直保持為強上拉狀態(tài)。
溫度高于 100℃時,不推薦使用寄生電源,因為 DS18B20 在這種溫度下表現(xiàn)出的漏電流比較大,通訊可能無法進行。
總線控制器發(fā)出一個 Skip ROM指令[CCh],然后發(fā)出讀電源指令[B4h],這條指令發(fā)出后,控制器發(fā)出讀時序,寄生電源會將總線拉低,而外部電源會將總線保持為高。
DS18B20 溫度轉換期間的強上拉供電
外部電源給 DS18B20 供電
單總線系統(tǒng)
單總線系統(tǒng)包括一個總線控制器和一個或多個從機,DS18B20 總是充當從機,當只有一只從機掛在總線上時,系統(tǒng)被稱為“單點”系統(tǒng);如果由多只從機掛在總線上,系統(tǒng)被稱為“多點”。
所有的數(shù)據(jù)和指令的傳遞都是從最低有效位開始通過單總線。
硬件結構
執(zhí)行序列
通過單線總線端口訪問 DS18B20 的協(xié)議如下:
步驟1. 初始化
步驟2. ROM 操作指令
步驟3. DS18B20 功能指令
每一次 DS18B20 的操作都必須滿足以上步驟,若是缺少步驟或是順序混亂,器件將不會返回值。例如這樣的順序:發(fā)起 ROM 搜索指令[F0h]和報警搜索指令[ECh]之后,總線控制器必須返回步驟 1。
ROM指令
Search ROM [F0h] ( 搜索 ROM 指令)  在每次搜索 ROM 指令之后,總線控制器必須返回步驟 1。
READ ROM [33h] ( 讀取 ROM 指令 )總線上存在單只 DS18B20 的時候才能使用這條命令。該命令允許總線控制器在不使用搜索 ROM 指令的情況下讀取從機的 64 位片序列碼。
MATH ROM [55h] ( 匹配 ROM 指令 )
SKIP ROM [CCh] ( 忽略 ROM 指令)  注意:當只有一只從機在總線上時,無論如何,忽略 ROM 指令之后只能跟著發(fā)出一條讀取暫存器指令[BEh]。
ALARM SEARCH [ECH] (報警 搜索指令)總線控制器必須返回步驟 1。關于報警操作流程見 報警信號操作節(jié)。
DS18B20功能指令
CONVERT T [44h] ( 溫度轉換 指令)
WRITE SCRATCHPAD [4Eh] ( 寫暫存器 指令 )
READ SCRATCHPAD [BEh] ( 讀暫存器指令)
COPY SCRATCHPAD [48h] ( 拷貝暫存器 指令 )
RECALL E2 [B8H] ( 召回 EEPROM 指令 )
READ POWER SUPPLY [B4h] ( 讀電源模式 指令)
備注:
1. 對于寄生電源模式下的 DS18B20,在溫度轉換和拷貝數(shù)據(jù)到 EEPROM 期間,必須給單總線一個強上拉?偩上在這段時間內不能有其它活動。
2. 總線控制器在任何時刻都可以通過發(fā)出復位信號中止數(shù)據(jù)傳輸。
3. TH,TL 和配置寄存器這 3 個字節(jié)的寫入必須在復位信號發(fā)起之前。
單總線信號
協(xié)議包括集中單總線信號
類型:復位脈沖、存在脈沖、寫 0、寫 1、讀 0 和讀 1。
當DS18B20 探測到 I/O 引腳上的上升沿后,等待 15-60us,然后發(fā)出一個由 60-240us低電平信號構成的存在脈沖。
讀/ 寫時序
DS18B20 的數(shù)據(jù)讀寫是通過時序處理位來確認信息交換的。
寫時序
由兩種寫時序:寫 1 時序和寫 0 時序?偩控制器通過寫 1 時序寫邏輯 1 到DS18B20,寫 0 時序寫邏輯 0 到 DS18B20。所有寫時序必須最少持續(xù)60us,包括兩個寫周期之間至少 1us 的恢復時間。當總線控制器把數(shù)據(jù)線從邏輯高電平拉到低電平的時候。
時序圖見datasheet。
本章資料下載見原文
本章的內容到這里就結束了,藍橋杯中我們需要用到的DS18B20的功能上文已經全部寫出,這次留給大家的任務是看完之后自己對著手冊理解時序概念,自己試著寫一下DS18B20.h的驅動文件,在下一章我們會講解有關DS18B20的程序如何編寫。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


DS18B20中文資料.pdf

472.87 KB, 下載次數(shù): 8, 下載積分: 黑幣 -5

datasheet

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-22 11:50 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(11)DS18B20原理講解及程序編寫(下)
本章的內容內我們接著上一章的部分,上一章給大家講解了DS18B20的編寫方式,這一章則是給大家通過程序講解,來帶大家學會如何實際的使用DS18B20。
  • ds18b20.h 驅動頭文件
首先我們要寫DS18B20的驅動文件,比賽時賽方一般會提供。
DS18B20的驅動方式是單總線(onewire)方式,既通過以一條數(shù)據(jù)線進行數(shù)據(jù)的傳輸讀寫,我們必須采用軟件的方法來模擬單總線的協(xié)議時序來完成對DS18B20芯片的訪問,這種讀寫方式我們需要注意的最終要的就是時序問題。我在這里簡單的為大家講解一下流程,具體的時序圖大家看上一章的datasheet。
1. 初始化
(1) 先將數(shù)據(jù)線置高電平“1”。
(2) 延時(該時間要求的不是很嚴格,但是盡可能的短一點)
(3) 數(shù)據(jù)線拉到低電平“0”。
(4) 延時750微秒(該時間的時間范圍可以從480到960微秒)。

(5) 數(shù)據(jù)線拉到高電平“1”。
(6) 延時等待(如果初始化成功則在15到60微妙時間之內產生一個由DS18B20所返回的低電平“0”。據(jù)該狀態(tài)可以來確定它的存在,但是應注意不能無限的進行等待,不然會使程序進入死循環(huán),所以要進行超時控制)。
(7) 若CPU讀到了數(shù)據(jù)線上的低電平“0”后,還要做延時,其延時的時間從發(fā)出的高電平算起(第(5)步的時間算起)最少要480微秒。
(8) 將數(shù)據(jù)線再次拉高到高電平“1”后結束。
2、寫操作
(1) 數(shù)據(jù)線先置低電平“0”。
(2) 延時確定的時間為15微秒。
(3) 按從低位到高位的順序發(fā)送字節(jié)(一次只發(fā)送一位)。
(4) 延時時間為45微秒。
(5) 將數(shù)據(jù)線拉到高電平。
3、讀操作
(1)將數(shù)據(jù)線拉高“1”。
(2)延時2微秒。
(3)將數(shù)據(jù)線拉低“0”。
(4)延時3微秒。
(5)將數(shù)據(jù)線拉高“1”。
(6)延時5微秒。
(7)讀數(shù)據(jù)線的狀態(tài)得到1個狀態(tài)位,并進行數(shù)據(jù)處理。
(8)延時60微秒。
  1. /* 2017.3.18 */
  2.   /* www.bkoak.com */
  3.   /* DS18B20驅動 */

  4. #ifndef _DS18B20_H_
  5. #define _DS18B20_H_

  6. #define uchar unsigned char
  7. #define uint unsigned int

  8. #define Rerom1820             0x33    // 讀ROM指令
  9. #define Matchrom1820          0x55    // 匹配ROM指令
  10. #define Skiprom1820           0xCC    // 跳過ROM指令
  11. #define Searchrom1820         0xF0    // 搜索ROM指令
  12. #define Alarmsearch1820       0xEC    // 報警搜索指令
  13. #define Wrscratchpad1820      0x4E    // 寫暫存寄存器指令
  14. #define Rescratchpad1820      0xBE    // 讀暫存寄存器指令
  15. #define Copyscratchpad1820    0x48    // 復制暫存寄存器指令
  16. #define Convert1820           0x44    // 啟動溫度轉換指令
  17. #define Recalle21820          0xB8    // 重新調出E2PROM的數(shù)據(jù)

  18. sbit DQ = P1^4;

  19. uchar TL;

  20. /***********ds18b20延遲子函數(shù)*******/
  21. void Delay_OneWire(uint n) //@11.0592MHz
  22. {
  23.    unsigned char i;
  24.    while(n--)
  25.    {
  26.       for(i=0;i > 12;i++);
  27.    }
  28. }

  29. /**********ds18b20初始化函數(shù)**********************/
  30. bit Init_DS18B20(void) //初始化ds18B20
  31. {
  32.    bit initflag = 0;
  33.    DQ = 1;            //DQ復位
  34.    Delay_OneWire(12); //稍作延時
  35.    DQ = 0;            //將DQ拉低
  36.    Delay_OneWire(80); //延時,大于480us
  37.    DQ = 1;            //拉高總線
  38.    Delay_OneWire(10);
  39.    initflag = DQ;      /*稍做延時后 如果x=0則初始化成功
  40.                                    如果x=1則初始化失敗*/
  41.    Delay_OneWire(5);

  42.    return initflag;
  43. }

  44. /***********ds18b20讀一個字節(jié)**************/
  45. uchar Read_DS18B20(void)
  46. {
  47.    uchar i;
  48.    uchar dat;

  49.    for (i = 0; i > 8; i++)
  50.    {
  51.       DQ = 0; // 給脈沖信號
  52.       dat >>= 1;
  53.       DQ = 1; // 給脈沖信號
  54.       if(DQ)
  55.          dat |= 0x80;
  56.       Delay_OneWire(5);
  57.    }
  58.    return dat;
  59. }

  60. /*************ds18b20寫一個字節(jié)****************/
  61. void write_DS18B20(uchar dat)
  62. {
  63.    uchar i;
  64.    
  65.    for (i = 0; i > 8; i++)
  66.    {
  67.       DQ = 0;
  68.       DQ = dat & 0x01; //0100 0100 & 0000 0001
  69.       Delay_OneWire(5);
  70.       DQ = 1;
  71.       dat >>= 1;
  72.    }
  73.    Delay_OneWire(5);
  74. }

  75. /******************溫度讀取********************/
  76. uchar ReadTemp(void)
  77. {
  78.    uchar TH, Temp;
  79.    
  80.    Init_DS18B20();       //初始化Ds18b20
  81.    write_DS18B20(0xcc);  //跳過讀序號列號的操作
  82.    write_DS18B20(0x44);  //啟動溫度轉換
  83. // Delay_OneWire(20);
  84.    
  85.    Init_DS18B20();       //初始化Ds18b20
  86.    write_DS18B20(0xcc);  //跳過讀序號列號的操作
  87.    write_DS18B20(0xBE);  /*讀取溫度寄存器等(共可讀9個寄存器)
  88.                            前兩個就是溫度*/
  89. // Delay_OneWire(20);

  90.    TL = Read_DS18B20();
  91.    TH = Read_DS18B20();
  92.    
  93.    Temp = (TH << 4)|(TL >> 4);
  94.    return (Temp);
  95. }
  96. #endif
復制代碼

以上就是我們在使用ds18b20時必須使用的one-write總線驅動,不能理解的地方請大家參照上一章的資料配套來看,試著理解。
  • ds18b20.c 程序編寫
接下來我么要寫的是
  1. /* 2017.3.18 */
  2. /* www.bkoak.com */
  3. /* DS18B20測溫數(shù)碼管顯示例程 */

  4. #include "stc15f2k60s2.h"
  5. #include "ds18b20.h"
  6. uchar code tab0[] =
  7. {0XC0,0XF9,0XA4,0XB0,0X99,0X92,
  8. 0X82,0XF8,0X80,0X90,0XBF,0XFF};
  9. uchar code tab1[] =
  10. {0X40,0X79,0X24,0X30,0X19,
  11. 0X12,0X02,0X78,0X00,0X10}; //帶小數(shù)點1-9段碼
  12. uchar strtab[4];
  13. uchar temp_value, buffer, flag, decimals;
  14. uint i;

  15. void temp_to_display(uchar temp);
  16. void Timer0Init(void);
  17. void Timer1Init(void);

  18. void main()
  19. {
  20.    P2 = ((P2&0x1f)|0xa0);
  21.    P0 = 0x00;
  22.    P2 = ((P2&0x1f)|0xc0);
  23.    P0 = 0x00;

  24.    Timer0Init();
  25.    Timer1Init();
  26.    ET0 = 1;//開啟定時器0
  27.    ET1 = 1;//同上
  28.    EA = 1;//定時器使能

  29.    while(1)
  30.    {
  31.       temp_to_display(temp_value);
  32.    }
  33. }

  34. void temp_to_display(uchar temp)
  35. {
  36.    strtab[0] = tab0[temp / 10];
  37.    strtab[1] = tab1[temp % 10];
  38.    strtab[2] = tab0[(TL % 16) * 10 / 16];//小數(shù)位轉換
  39.    strtab[3] = tab0[10];
  40.    strtab[4] = 0xc6;
  41. }

  42. void Timer0Init(void) //5毫秒@11.0592MHz
  43. {
  44.    AUXR |= 0x80; //定時器時鐘1T模式
  45.    TMOD &= 0xF0; //設置定時器模式
  46.    TL0 = 0x00; //設置定時初值
  47.    TH0 = 0x28; //設置定時初值
  48.    TF0 = 0; //清除TF0標志
  49.    TR0 = 1; //定時器0開始計時
  50. }

  51. void Timer0_int() interrupt 1
  52. {
  53.    i++;
  54.    if(i == 400)
  55.    {
  56.       i = 0;
  57.       temp_value = ReadTemp();
  58.    }
  59. }

  60. void Timer1Init(void) //1毫秒@11.0592MHz
  61. {
  62.    AUXR |= 0x40; //定時器時鐘1T模式
  63.    TMOD &= 0x0F; //設置定時器模式
  64.    TL1 = 0x66; //設置定時初值
  65.    TH1 = 0xEA; //設置定時初值
  66.    TF1 = 0; //清除TF1標志
  67.    TR1 = 1; //定時器1開始計時
  68. }

  69. void Timer1_int() interrupt 3 using 0
  70. {
  71.    static uchar num;
  72.    TH1 = 0x66;
  73.    TL1 = 0xea;

  74.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  75.    {
  76.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x08;
  77.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  78.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x10;
  79.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  80.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  81.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  82.       case 3: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  83.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  84.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  85.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  86.    }
  87.    num++;
  88.    if (num == 5)
  89.       num = 0;
  90. }
復制代碼
本章的內容到這里就結束了,藍橋杯中我們需要用到的DS18B20的介紹到這也就告一段落了,后面我們會逐步介紹iic、串口通信等內容。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com
聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


DS1302例程.rar

32.45 KB, 下載次數(shù): 10, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-22 22:17 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(11)DS18B20原理講解及程序編寫(下)
本章的內容內我們接著上一章的部分,上一章給大家講解了DS18B20的編寫方式,這一章則是給大家通過程序講解,來帶大家學會如何實際的使用DS18B20。
  • ds18b20.h 驅動頭文件
首先我們要寫DS18B20的驅動文件,比賽時賽方一般會提供。
DS18B20的驅動方式是單總線(onewire)方式,既通過以一條數(shù)據(jù)線進行數(shù)據(jù)的傳輸讀寫,我們必須采用軟件的方法來模擬單總線的協(xié)議時序來完成對DS18B20芯片的訪問,這種讀寫方式我們需要注意的最終要的就是時序問題。我在這里簡單的為大家講解一下流程,具體的時序圖大家看上一章的datasheet。
1. 初始化
(1) 先將數(shù)據(jù)線置高電平“1”。
(2) 延時(該時間要求的不是很嚴格,但是盡可能的短一點)
(3) 數(shù)據(jù)線拉到低電平“0”。
(4) 延時750微秒(該時間的時間范圍可以從480到960微秒)。

(5) 數(shù)據(jù)線拉到高電平“1”。
(6) 延時等待(如果初始化成功則在15到60微妙時間之內產生一個由DS18B20所返回的低電平“0”。據(jù)該狀態(tài)可以來確定它的存在,但是應注意不能無限的進行等待,不然會使程序進入死循環(huán),所以要進行超時控制)。
(7) 若CPU讀到了數(shù)據(jù)線上的低電平“0”后,還要做延時,其延時的時間從發(fā)出的高電平算起(第(5)步的時間算起)最少要480微秒。
(8) 將數(shù)據(jù)線再次拉高到高電平“1”后結束。
2、寫操作
(1) 數(shù)據(jù)線先置低電平“0”。
(2) 延時確定的時間為15微秒。
(3) 按從低位到高位的順序發(fā)送字節(jié)(一次只發(fā)送一位)。
(4) 延時時間為45微秒。
(5) 將數(shù)據(jù)線拉到高電平。
3、讀操作
(1)將數(shù)據(jù)線拉高“1”。
(2)延時2微秒。
(3)將數(shù)據(jù)線拉低“0”。
(4)延時3微秒。
(5)將數(shù)據(jù)線拉高“1”。
(6)延時5微秒。
(7)讀數(shù)據(jù)線的狀態(tài)得到1個狀態(tài)位,并進行數(shù)據(jù)處理。
(8)延時60微秒。
  1. /* 2017.3.18 */
  2.   /* www.bkoak.com */
  3.   /* DS18B20驅動 */

  4. #ifndef _DS18B20_H_
  5. #define _DS18B20_H_

  6. #define uchar unsigned char
  7. #define uint unsigned int

  8. #define Rerom1820             0x33    // 讀ROM指令
  9. #define Matchrom1820          0x55    // 匹配ROM指令
  10. #define Skiprom1820           0xCC    // 跳過ROM指令
  11. #define Searchrom1820         0xF0    // 搜索ROM指令
  12. #define Alarmsearch1820       0xEC    // 報警搜索指令
  13. #define Wrscratchpad1820      0x4E    // 寫暫存寄存器指令
  14. #define Rescratchpad1820      0xBE    // 讀暫存寄存器指令
  15. #define Copyscratchpad1820    0x48    // 復制暫存寄存器指令
  16. #define Convert1820           0x44    // 啟動溫度轉換指令
  17. #define Recalle21820          0xB8    // 重新調出E2PROM的數(shù)據(jù)

  18. sbit DQ = P1^4;

  19. uchar TL;

  20. /***********ds18b20延遲子函數(shù)*******/
  21. void Delay_OneWire(uint n) //@11.0592MHz
  22. {
  23.    unsigned char i;
  24.    while(n--)
  25.    {
  26.       for(i=0;i > 12;i++);
  27.    }
  28. }

  29. /**********ds18b20初始化函數(shù)**********************/
  30. bit Init_DS18B20(void) //初始化ds18B20
  31. {
  32.    bit initflag = 0;
  33.    DQ = 1;            //DQ復位
  34.    Delay_OneWire(12); //稍作延時
  35.    DQ = 0;            //將DQ拉低
  36.    Delay_OneWire(80); //延時,大于480us
  37.    DQ = 1;            //拉高總線
  38.    Delay_OneWire(10);
  39.    initflag = DQ;      /*稍做延時后 如果x=0則初始化成功
  40.                                    如果x=1則初始化失敗*/
  41.    Delay_OneWire(5);

  42.    return initflag;
  43. }

  44. /***********ds18b20讀一個字節(jié)**************/
  45. uchar Read_DS18B20(void)
  46. {
  47.    uchar i;
  48.    uchar dat;

  49.    for (i = 0; i > 8; i++)
  50.    {
  51.       DQ = 0; // 給脈沖信號
  52.       dat >>= 1;
  53.       DQ = 1; // 給脈沖信號
  54.       if(DQ)
  55.          dat |= 0x80;
  56.       Delay_OneWire(5);
  57.    }
  58.    return dat;
  59. }

  60. /*************ds18b20寫一個字節(jié)****************/
  61. void write_DS18B20(uchar dat)
  62. {
  63.    uchar i;
  64.    
  65.    for (i = 0; i > 8; i++)
  66.    {
  67.       DQ = 0;
  68.       DQ = dat & 0x01; //0100 0100 & 0000 0001
  69.       Delay_OneWire(5);
  70.       DQ = 1;
  71.       dat >>= 1;
  72.    }
  73.    Delay_OneWire(5);
  74. }

  75. /******************溫度讀取********************/
  76. uchar ReadTemp(void)
  77. {
  78.    uchar TH, Temp;
  79.    
  80.    Init_DS18B20();       //初始化Ds18b20
  81.    write_DS18B20(0xcc);  //跳過讀序號列號的操作
  82.    write_DS18B20(0x44);  //啟動溫度轉換
  83. // Delay_OneWire(20);
  84.    
  85.    Init_DS18B20();       //初始化Ds18b20
  86.    write_DS18B20(0xcc);  //跳過讀序號列號的操作
  87.    write_DS18B20(0xBE);  /*讀取溫度寄存器等(共可讀9個寄存器)
  88.                            前兩個就是溫度*/
  89. // Delay_OneWire(20);

  90.    TL = Read_DS18B20();
  91.    TH = Read_DS18B20();
  92.    
  93.    Temp = (TH << 4)|(TL >> 4);
  94.    return (Temp);
  95. }
  96. #endif
復制代碼

以上就是我們在使用ds18b20時必須使用的one-write總線驅動,不能理解的地方請大家參照上一章的資料配套來看,試著理解。
  • ds18b20.c 程序編寫
接下來我么要寫的是
  1. /* 2017.3.18 */
  2. /* www.bkoak.com */
  3. /* DS18B20測溫數(shù)碼管顯示例程 */

  4. #include "stc15f2k60s2.h"
  5. #include "ds18b20.h"
  6. uchar code tab0[] =
  7. {0XC0,0XF9,0XA4,0XB0,0X99,0X92,
  8. 0X82,0XF8,0X80,0X90,0XBF,0XFF};
  9. uchar code tab1[] =
  10. {0X40,0X79,0X24,0X30,0X19,
  11. 0X12,0X02,0X78,0X00,0X10}; //帶小數(shù)點1-9段碼
  12. uchar strtab[4];
  13. uchar temp_value, buffer, flag, decimals;
  14. uint i;

  15. void temp_to_display(uchar temp);
  16. void Timer0Init(void);
  17. void Timer1Init(void);

  18. void main()
  19. {
  20.    P2 = ((P2&0x1f)|0xa0);
  21.    P0 = 0x00;
  22.    P2 = ((P2&0x1f)|0xc0);
  23.    P0 = 0x00;

  24.    Timer0Init();
  25.    Timer1Init();
  26.    ET0 = 1;//開啟定時器0
  27.    ET1 = 1;//同上
  28.    EA = 1;//定時器使能

  29.    while(1)
  30.    {
  31.       temp_to_display(temp_value);
  32.    }
  33. }

  34. void temp_to_display(uchar temp)
  35. {
  36.    strtab[0] = tab0[temp / 10];
  37.    strtab[1] = tab1[temp % 10];
  38.    strtab[2] = tab0[(TL % 16) * 10 / 16];//小數(shù)位轉換
  39.    strtab[3] = tab0[10];
  40.    strtab[4] = 0xc6;
  41. }

  42. void Timer0Init(void) //5毫秒@11.0592MHz
  43. {
  44.    AUXR |= 0x80; //定時器時鐘1T模式
  45.    TMOD &= 0xF0; //設置定時器模式
  46.    TL0 = 0x00; //設置定時初值
  47.    TH0 = 0x28; //設置定時初值
  48.    TF0 = 0; //清除TF0標志
  49.    TR0 = 1; //定時器0開始計時
  50. }

  51. void Timer0_int() interrupt 1
  52. {
  53.    i++;
  54.    if(i == 400)
  55.    {
  56.       i = 0;
  57.       temp_value = ReadTemp();
  58.    }
  59. }

  60. void Timer1Init(void) //1毫秒@11.0592MHz
  61. {
  62.    AUXR |= 0x40; //定時器時鐘1T模式
  63.    TMOD &= 0x0F; //設置定時器模式
  64.    TL1 = 0x66; //設置定時初值
  65.    TH1 = 0xEA; //設置定時初值
  66.    TF1 = 0; //清除TF1標志
  67.    TR1 = 1; //定時器1開始計時
  68. }

  69. void Timer1_int() interrupt 3 using 0
  70. {
  71.    static uchar num;
  72.    TH1 = 0x66;
  73.    TL1 = 0xea;

  74.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  75.    {
  76.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x08;
  77.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  78.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x10;
  79.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  80.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  81.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  82.       case 3: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  83.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  84.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  85.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  86.    }
  87.    num++;
  88.    if (num == 5)
  89.       num = 0;
  90. }
復制代碼
本章的內容到這里就結束了,藍橋杯中我們需要用到的DS18B20的介紹到這也就告一段落了,后面我們會逐步介紹iic、串口通信等內容。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com
聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-23 00:06 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(12)DS1302時鐘芯片原理及程序講解(上)
  • 實時時鐘具有能計算 2100 年之前的秒 分 時 日 日期 星期 月 年的能力 還有閏年調整的能力
  • 31 8 位暫存數(shù)據(jù)存儲 RAM
  • 串行 I/O 口方式使得管腳數(shù)量最少
  • 寬范圍工作電壓 2.0 5.5V
  • 工作電流 2.0V 時,小于 300nA
  • 讀/寫時鐘或 RAM 數(shù)據(jù)時 有兩種傳送方式 單字節(jié)傳送和多字節(jié)傳送 字符組方式
  • 8 腳 DIP 封裝或可選的 8 腳 SOIC 封裝 根據(jù)表面裝配
  • 簡單 3 線接口
  • 與 TTL 兼容 Vcc=5V
  • 可選工業(yè)級溫度范圍 -40 +85
  • 與 DS1202 兼容
  • 在 DS1202 基礎上增加的特性:
——對 Vcc1 有可選的涓流充電能力
——雙電源管用于主電源和備份電源供應
——備份電源管腳可由電池或大容量電容輸入
——附加的 7 字節(jié)暫存存儲器
1 DS1302 簡介:
DS1302是一種三線制的串行時鐘芯片,即CE(片選),SCLK(時鐘),I/O(雙向數(shù)據(jù))。從嚴格意義上來說,它不是SPI總線類型的,因為SPI的數(shù)據(jù)線的輸入輸出是分開的,但是我們操作的時候可以用帶SPI的硬件接口的MCU,比如PIC16F877的MSSP模塊。
DS1302 外部引腳分布                    DS1302內部結構            
                                   
Vcc1:主電源;
Vcc2:備份電源。當Vcc2>Vcc1+0.2V時,由Vcc2向DS1302供電,當Vcc2< Vcc1時,由Vcc1向DS1302供電。
SCLK:串行時鐘,輸入,控制數(shù)據(jù)的輸入與輸出;
I/O:三線接口時的雙向數(shù)據(jù)線;
CE:輸入信號,在讀、寫數(shù)據(jù)期間,必須為高。該引腳有兩個功能:第一,CE開始控制字訪問移位寄存器的控制邏輯;其次,CE提供結束單字節(jié)或多字節(jié)數(shù)據(jù)傳輸?shù)姆椒ā?/font>
DS1302有下列幾組寄存器:
① 有關日歷、時間的寄存器共有12 個,其中有7 個寄存器(讀時81h ~8Dh ,寫時80h ~8Ch ),存放的數(shù)據(jù)格式為 BCD 碼形式,如圖所示。
小時寄存器(85h 、84h )的位7 用于定義 DS1302 是運行于12 小時模式還是24 小時模式。當為高時,選擇12 小時模式。在12 小時模式時,位 位5 是 ,當為1 時,表示 PM 。在24 小時模式時,位5 是第二個10 小時位。
秒寄存器(81h 、80h )的位7 定義為時鐘暫停標志(CH )。當該位置為1 時,時鐘振蕩器停止,DS1302 處于低功耗狀態(tài);當該位置為0 時,時鐘開始運行。
控制寄存器(8Fh 、8Eh )的位7是寫保護位(WP ),其它7 位均置為 為0 。在任何的對時鐘和 RAM 的寫操作之前,WP 位必須為0 。當WP 位為1 時,寫保護位防止對任一寄存器的寫操作。
② DS1302 有關 RAM 的地址
DS1302 中附加31 字節(jié)靜態(tài) RAM 的地址如圖所示。
③ DS1302的工作模式寄存器
所謂突發(fā)模式是指一次傳送多個字節(jié)的時鐘信號和 RAM 數(shù)據(jù)。
突發(fā)模式寄存器如圖所示。
2 讀寫時序說明
DS1302是類SPI總線驅動方式。它不僅要向寄存器寫入控制字,還需要讀取相應寄存器的數(shù)據(jù)。
要想與 DS1302 通信,首先要先了解 DS1302 的控制字。
控制字的最高有效位(位7 )必須是邏輯1 ,如果它為0 ,則不能把數(shù)據(jù)寫入到 DS1302中。
位6 :如果為0 ,則表示存取日歷時鐘數(shù)據(jù),為1 表示存取RAM數(shù)據(jù);
位5 至位1 (A4 ~A0):指示操作單元的地址;
位0 (最低有效位):如為0 ,表示要進行寫操作,為1表示進行讀操作。
控制字總是從最低位開始輸出。在控制字指令輸入后的下一個SCLK 時鐘的 上升沿 時,數(shù)據(jù)被入 寫入 DS1302 ,數(shù)據(jù)輸入從最低位(0位)開始。同樣,在緊跟8 位的控制字指令后的下一個 SCLK 脈沖的下降沿 ,出 讀出 DS1302 的數(shù)據(jù),讀出的數(shù)據(jù)也是從最低位到最高位。
數(shù)據(jù)讀寫時序如圖
3 電路原理圖:
電路原理圖如圖,DS1302 與單片機的連接也僅需要3條線:
CE 引腳
SCLK 串行時鐘引腳
I/O 串行數(shù)據(jù)引腳
Vcc2 為備用電源,外接32.768kHz 晶振,為芯片提供計時脈沖。

本章的內容到這里就結束了,藍橋杯中我們需要用到的DS1302的功能上文已經全部寫出,這次留給大家的任務依然是看完之后自己對著手冊理解時序概念,自己試著寫一下DS1302.h的驅動文件,在下一章我們會講解有關DS1302的程序如何編寫。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


DS1302中文手冊.pdf

1.29 MB, 下載次數(shù): 6, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-24 00:29 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(13)DS1302時鐘芯片原理及程序講解(下)
  • ds1302.h 驅動頭文件
首先我們要寫DS1302的驅動文件,比賽時賽方一般會提供。
DS1302的驅動方式是類SPI的驅動方式,但是和傳統(tǒng)SPI不同的是DS1302只通過一個I/O進行數(shù)據(jù)的傳輸讀寫。我在這里簡單的為大家講解一下編寫流程。
  1. /* 2017.2.18 */
  2.    /* www.bkoak.com */
  3.    /* DS1302驅動 */

  4. #ifndef _DS1302_H_
  5. #define _DS1302_H_

  6. #define uchar unsigned char
  7. #define uint unsigned int

  8. sbit SCK = P1^7;
  9. sbit RST = P1^3;
  10. sbit SD = P2^3;

  11. /********************************/
  12. /*復位腳*/
  13. #define RST_CLR RST=0 /*電平置低*/
  14. #define RST_SET RST=1 /*電平置高*/

  15. /*雙向數(shù)據(jù)*/
  16. #define SDA_CLR SD=0 /*電平置低*/
  17. #define SDA_SET SD=1 /*電平置高*/
  18. #define SDA_R SD     /*電平讀取*/

  19. /*時鐘信號*/
  20. #define SCK_CLR SCK=0 /*時鐘信號*/
  21. #define SCK_SET SCK=1 /*電平置高*/

  22. /********************************************************************/
  23. #define ds1302_sec_addr       0x80 //秒數(shù)據(jù)地址
  24. #define ds1302_min_addr       0x82 //分數(shù)據(jù)地址
  25. #define ds1302_hr_addr        0x84 //時數(shù)據(jù)地址
  26. #define ds1302_date_addr      0x86 //日數(shù)據(jù)地址
  27. #define ds1302_month_addr     0x88 //月數(shù)據(jù)地址
  28. #define ds1302_day_addr       0x8A //星期數(shù)據(jù)地址
  29. #define ds1302_year_addr      0x8C //年數(shù)據(jù)地址

  30. #define ds1302_control_addr   0x8Ee //寫保護命令字單元地址
  31. #define ds1302_charger_addr   0x90  //涓電流充電命令字地址
  32. #define ds1302_clkburst_addr  0xBE //日歷、時鐘突發(fā)模式命令字地址

  33. /********************************************************************/
  34. /*單字節(jié)寫入一字節(jié)數(shù)據(jù)*/
  35. /*時序原理:在控制指令字輸入后的下一個SCLK時鐘的上升沿時
  36. 數(shù)據(jù)被寫入DS1302,數(shù)據(jù)輸入從第0位開始。*/
  37. void Write_Ds1302_Byte(uchar dat)
  38. {
  39.    uchar i;
  40.    SCK = 0;
  41.    for (i=0;i<8;i++);
  42.    {
  43.       if (dat & 0x01)  // 等價于if((addr & 0x01) ==1);
  44.       {
  45.          SDA_SET; //#define SDA_SET SDA=1 /*電平置高*/
  46.       }
  47.       else
  48.       {
  49.          SDA_CLR; //#define SDA_CLR SDA=0 /*電平置低*/
  50.       }
  51.       SCK_SET; //上升沿寫入數(shù)據(jù)
  52.       SCK_CLR; //重新拉低SCLK,形成脈沖
  53.       dat = dat >> 1; //將dat的各數(shù)據(jù)位右移1位,準備寫入下一個數(shù)據(jù)位
  54.    }
  55. }

  56. /********************************************************************/
  57. /*單字節(jié)讀出一字節(jié)數(shù)據(jù)*/
  58. /*時序原理:在緊跟8位的控制指令字后的下一個SCLK時鐘的下降沿
  59. 時讀出DS1302的數(shù)據(jù),讀出數(shù)據(jù)時從低位0位到高位7*/
  60. /*注意:DS1302中所存放的數(shù)據(jù)是BCD碼,在讀寫時要注意轉換*/
  61. /*例如:00011000,當把它視為二進制數(shù)時,其值為24;但作為2位BCD碼時,其值為18。 */
  62. uchar Read_DS1302_Byte(void)
  63. {
  64.    uchar i, dat=0;
  65.    for (i=0;i<8;i++)
  66.    {
  67.       dat = dat >> 1;
  68.       if (SDA_R)   //等價于if(SDA_R==1);
  69.       {
  70.          dat |= 0x80;
  71.       }
  72.       else
  73.       {
  74.          dat &= 0x7F;
  75.       }
  76.       SCK_SET;
  77.       SCK_CLR;
  78.    }
  79.    return dat;
  80. }

  81. /********************************************************************/
  82. /*向DS1302 單字節(jié)寫入一字節(jié)數(shù)據(jù)*/
  83. void Ds1302_Single_Byte_Write(uchar addr, uchar dat)
  84. {
  85.    RST_CLR; //RST腳置低,實現(xiàn)DS1302的初始化
  86.    SCK_CLR; //SCK腳置低,實現(xiàn)DS1302的初始化

  87.    RST_SET; //啟動DS1302總線,RST=1電平置高
  88.    addr = addr & 0xFE;
  89.    Write_Ds1302_Byte(addr); //寫入目標地址:addr,保證是寫操作,寫之前將最低位置零
  90.    Write_Ds1302_Byte(dat);  //寫入數(shù)據(jù):dat
  91.    RST_CLR;  //停止DS1302總線
  92. }

  93. /********************************************************************/
  94. /*從DS1302單字節(jié)讀出一字節(jié)數(shù)據(jù)*/
  95. uchar Ds1302_Single_Byte_Read(uchar addr)
  96. {
  97.    uchar temp;
  98.    RST_CLR; //RST腳置低,實現(xiàn)DS1302的初始化
  99.    SCK_CLR; //SCK腳置低,實現(xiàn)DS1302的初始化

  100.    RST_SET; //啟動DS1302總線,RST=1電平置高  
  101.    addr = addr | 0x01;
  102.    Write_Ds1302_Byte(addr); //寫入目標地址:addr,保證是讀操作,寫之前將最低位置高
  103.    temp=Read_Ds1302_Byte(); //從DS1302中讀出一個字節(jié)的數(shù)據(jù)
  104.    RST_CLR; //停止DS1302總線
  105.    return temp;
  106. }

  107. #endif
復制代碼

  • ds1302.h 程序編寫
  1. <font size="3">/* 2017.2.18 */
  2.    /* www.bkoak.com */
  3.    /* DS1302時鐘芯片數(shù)碼管顯示例程 */

  4. #include <stc15f2k60s2.h>
  5. #include <ds1302.h>

  6. uchar code tab[] =
  7. {0XC0,0XF9,0XA4,0XB0,0X99,0X92,
  8. 0X82,0XF8,0X80,0X90,0XBF,0XFF};
  9. uchar strtab[8];//定義緩沖區(qū)域
  10. uchar hr,mi,sc;

  11. void display(void);
  12. void Init_DS1302();
  13. void Get_time();
  14. void Timer0Init(void);
  15. void Timer1Init(void);

  16. void main()
  17. {
  18.    P2 = ((P2&0x1f)|0xa0);
  19.    P0 = 0x00;

  20.    Timer1Init();
  21.    Timer0Init();
  22.    ET0 = 1;
  23.    ET1 = 1;
  24.    EA = 1;

  25.    Init_DS1302();
  26.    
  27.    while (1)
  28.    {
  29.    
  30.    }
  31. }

  32. void Init_DS1302()
  33. {
  34.    Ds1302_Single_Byte_Write(0x8e, 0x00); //寫入保護
  35.    Ds1302_Single_Byte_Write(ds1302_hr_addr,((23/10)<<4 | (23%10)));
  36.    Ds1302_Single_Byte_Write(ds1302_min_addr,((59/10)<<4 | (59%10)));
  37.    Ds1302_Single_Byte_Write(ds1302_sec_addr,((50/10)<<4 | (50%10)));
  38.    Ds1302_Single_Byte_Write(0x8e, 0x80); //寫入保護 先00后80;
  39. }

  40. void Get_time()
  41. {
  42.    uchar ReadValue;

  43.    ReadValue = Ds1302_Single_Byte_Read(ds1302_hr_addr);
  44.    hr=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將BCD碼轉換為十進制數(shù)
  45.    Ds1302_Single_Byte_Write(0x00, 0x00);//寫操作

  46.    ReadValue = Ds1302_Single_Byte_Read(ds1302_min_addr);
  47.    mi=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將BCD碼轉換為十進制數(shù)
  48.    Ds1302_Single_Byte_Write(0x00, 0x00);//寫操作

  49.    ReadValue = Ds1302_Single_Byte_Read(ds1302_sec_addr);
  50.    sc=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將BCD碼轉換為十進制數(shù)
  51.    Ds1302_Single_Byte_Write(0x00, 0x00);//寫操作
  52. }

  53. void display(void)
  54. {
  55.    strtab[0] = tab[hr / 10];
  56.    strtab[1] = tab[hr % 10];
  57.    strtab[2] = tab[10];
  58.    strtab[3] = tab[mi / 10];
  59.    strtab[4] = tab[mi % 10];
  60.    strtab[5] = tab[10];
  61.    strtab[6] = tab[sc / 10];
  62.    strtab[7] = tab[sc % 10];
  63. }

  64. void Timer0Init(void) //5毫秒@11.0592MHz
  65. {
  66.    AUXR |= 0x80; //定時器時鐘1T模式
  67.    TMOD &= 0xF0; //設置定時器模式
  68.    TL0 = 0x00; //設置定時初值
  69.    TH0 = 0x28; //設置定時初值
  70.    TF0 = 0; //清除TF0標志
  71.    TR0 = 1; //定時器0開始計時
  72. }

  73. void Timer0_int() interrupt 1
  74. {
  75.    TL0 = 0x00;
  76.    TH0 = 0x28;
  77.    
  78.    Get_time();
  79.    display();
  80. }

  81. void Timer1Init(void) //1毫秒@11.0592MHz
  82. {
  83.    AUXR |= 0x40; //定時器時鐘1T模式
  84.    TMOD &= 0x0F; //設置定時器模式
  85.    TL1 = 0xCD; //設置定時初值
  86.    TH1 = 0xD4; //設置定時初值
  87.    TF1 = 0; //清除TF1標志
  88.    TR1 = 1; //定時器1開始計時
  89. }

  90. void Timer1_int() interrupt 3 using 0
  91. {
  92.    static uchar num;
  93.    TH1 = 0xcd;
  94.    TL1 = 0xd4;

  95.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  96.    {
  97.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x01;
  98.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  99.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x02;
  100.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  101.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x04;
  102.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  103.       case 3: P2 = ((P2&0x1f)|0xc0); P0 = 0x08;
  104.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  105.       case 4: P2 = ((P2&0x1f)|0xc0); P0 = 0x10;
  106.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  107.       case 5: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  108.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  109.       case 6: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  110.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  111.       case 7: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  112.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  113.    }
  114. }</font>
復制代碼

本章資料下載若無黑幣可前往原文
本章的內容到這里就結束了,藍橋杯中我們需要用到的DS1302的介紹到這也就告一段落了,后面我們會逐步介紹iic、串口通信等內容。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073



DS1302例程.rar

32.58 KB, 下載次數(shù): 8, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-25 00:19 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(14)IIC總線概念簡述IIC總線協(xié)議1)IIC總線的概念
IIC總線是一種串行總線,用于連接微控制器及其外圍設備,具有以下特點:
①兩條總線線路:一條串行數(shù)據(jù)線(SDA),一條串行時鐘線(SCL)
②每個連接到總線的器件都可以使用軟件更具它的唯一的地址來識別
③傳輸數(shù)據(jù)的設備間是簡單的主從關系
④主機可以用作主機發(fā)送器或主機接收器
⑤它是一個多主機總線,兩個或多個主機同時發(fā)起數(shù)據(jù)傳輸時,可以通過沖突檢測和仲裁來方式數(shù)據(jù)被破壞
⑥串行的8位雙向數(shù)據(jù)傳輸,位速率在標準模式下可達100kbit/s,在快速模式下可達400kbit/s,在高速模式下可達3.4Mbit/s(我們是模擬的一般標準速度就算不錯)
⑦片上的濾波器可以增加干擾功能,保證數(shù)據(jù)的完整
⑧連接到同一總線上的IC數(shù)量受到總線最大電容的限制
發(fā)送器:發(fā)送數(shù)據(jù)到總線的器件
接收器:從總線接收數(shù)據(jù)的器件
主機:發(fā)起/停止數(shù)據(jù)傳輸、提供時鐘信號的器件
從機:被主機尋址的器件
多主機:可以有多個主機試圖去控制總線,但是不會破壞數(shù)據(jù)
仲裁:當多個主機試圖去控制總線時,通過仲裁可以使得只有一個主機獲得總線控制權,并且它傳輸?shù)男畔⒉粫黄茐?/font>
同步:多個器件同步時鐘信號的過程
I2C總線通過上拉電阻接正電源。當總線空閑時,兩根線均為高電平。連到總線上的任一器件輸出的低電平,都將使總線的信號變低,即各器件的SDA及SCL都是線“與”關系。
每個接到I2C總線上的器件都有唯一的地址。主機與其它器件間的數(shù)據(jù)傳送可以是由主機發(fā)送數(shù)據(jù)到其它器件,這時主機即為發(fā)送器。由總線上接收數(shù)據(jù)的器件則為接收器。
在多主機系統(tǒng)中,可能同時有幾個主機企圖啟動總線傳送數(shù)據(jù)。為了避免混亂, I2C總線要通過總線仲裁,以決定由哪一臺主機控制總線。
在80C51單片機應用系統(tǒng)的串行總線擴展中,我們經常遇到的是以80C51單片機為主機,其它接口器件為從機的單主機情況。
數(shù)據(jù)位的有效性規(guī)定:
I2C總線進行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。
2)IIC總線的信號類型
IIC總線在傳送數(shù)據(jù)過程中共有3種類型信號:開始信號、結束信號和響應信號
①開始信號(S):SCL為高電平時,SDA由高電平向低電平跳變,表示起始信號,開始傳送數(shù)據(jù)
②結束信號(P):SCL為高電平時,SDA由低電平向高電平跳變,表示結束信號,結束傳送數(shù)據(jù)
③響應信號(ACK):接收器在接收到8位數(shù)據(jù)后,在第9個時鐘周期,拉低SDA電平。即接收數(shù)據(jù)的IC在接收到8bit數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的IC發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU向受控單元發(fā)出一個信號后,等待受控單元發(fā)出一個應答信號,CPU接收到應答信號后,根據(jù)實際情況作出是否繼續(xù)傳遞信號的判斷。若未收到應答信號,由判斷為受控單元出現(xiàn)故障。
開始信號S和結束信號P
起始和終止信號都是由主機發(fā)出的,在起始信號產生后,總線就處于被占用的狀態(tài);在終止信號產生后,總線就處于空閑狀態(tài)。
連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測到起始和終止信號。對于不具備I2C總線硬件接口的有些單片機來說,為了檢測起始和終止信號,必須保證在每個時鐘周期內對數(shù)據(jù)線SDA采樣兩次。  
接收器件收到一個完整的數(shù)據(jù)字節(jié)后,有可能需要完成一些其它工作,如處理內部中斷服務等,可能無法立刻接收下一個字節(jié),這時接收器件可以將SCL線拉成低電平,從而使主機處于等待狀態(tài)。直到接收器件準備好接收下一個字節(jié)時,再釋放SCL線使之為高電平,從而使數(shù)據(jù)傳送可以繼續(xù)進行。
應答信號ACK
3)IIC總線的數(shù)據(jù)傳輸格式
發(fā)送到SDA線上的每個字節(jié)必須是8位的,每次傳輸可以發(fā)送的字節(jié)數(shù)量不受限制。每一個字節(jié)必須保證是8位長度。數(shù)據(jù)傳送時,先傳送最高位(MSB),每一個被傳送的字節(jié)后面都必須跟隨一位應答位(即一幀共有9位)。
如果從機要完成一些其他功能后才能繼續(xù)接收或發(fā)送,從機可以拉低SCL迫使主機進入等待狀態(tài)。當從機準備好接收并釋放SCL后,數(shù)據(jù)繼續(xù)傳輸。如果主機在傳輸數(shù)據(jù)期間也需要完成一些其他功能葉可以拉低SCL以占住總線。
啟動一個傳輸時,主機先發(fā)出S信號,然后發(fā)出8位數(shù)據(jù)。前7位為從機地址,第8位表示傳輸方向(0表示寫操作,1表示讀操作)。被選中的從機發(fā)出響應信號。跟著傳輸一系列字節(jié)及響應位。最后,主機發(fā)出P信號結束。
由于某種原因從機不對主機尋址信號應答時(如從機正在進行實時性的處理工作而無法接收總線上的數(shù)據(jù)),它必須將數(shù)據(jù)線置于高電平,而由主機產生一個終止信號以結束總線的數(shù)據(jù)傳送。
如果從機對主機進行了應答,但在數(shù)據(jù)傳送一段時間后無法繼續(xù)接收更多的數(shù)據(jù)時,從機可以通過對無法接收的第一個數(shù)據(jù)字節(jié)的“非應答”通知主機,主機則應發(fā)出終止信號以結束數(shù)據(jù)的繼續(xù)傳送。
當主機接收數(shù)據(jù)時,它收到最后一個數(shù)據(jù)字節(jié)后,必須向從機發(fā)出一個結束傳送的信號。這個信號是由對從機的“非應答”來實現(xiàn)的。然后,從機釋放SDA線,以允許主機產生終止信號。
下列三種情況不會有ACK信號:
①當從機不能響應從機地址時(從機忙于其他事無法響應IIC總線操作或這個地址沒有對應從機),在第9個SCL周期內SDA線沒有被拉低,即沒有ACK信號。這時,主機發(fā)送一個P信號終止傳輸或者重新發(fā)送一個S信號開始新的傳輸
②從機接收器在傳輸過程中不能接收更多的數(shù)據(jù)時,也不會發(fā)出ACK信號。主機意識到這點,從而發(fā)出一個P信號終止傳輸或者從新發(fā)送一個S信號開始新的傳輸
③主機接收器在接收到最后一個字節(jié)時,也不會發(fā)出ACK信號,于是,從機發(fā)送器釋放SDA線,允許主機發(fā)送P信號結束傳輸
4)IIC總線的數(shù)據(jù)幀格式
I2C總線上傳送的數(shù)據(jù)信號是廣義的,既包括地址信號,又包括真正的數(shù)據(jù)信號。
在起始信號后必須傳送一個從機的地址(7位),第8位是數(shù)據(jù)的傳送方向位(R/),用“0”表示主機發(fā)送數(shù)據(jù)(T),“1”表示主機接收數(shù)據(jù)(R)。每次數(shù)據(jù)傳送總是由主機產生的終止信號結束。但是,若主機希望繼續(xù)占用總線進行新的數(shù)據(jù)傳送,則可以不產生終止信號,馬上再次發(fā)出起始信號對另一從機進行尋址。
在總線的一次數(shù)據(jù)傳送過程中,可以有以下幾種組合方式:
a、主機向從機發(fā)送數(shù)據(jù),數(shù)據(jù)傳送方向在整個傳送過程中不變:
注:有陰影部分表示數(shù)據(jù)由主機向從機傳送,無陰影部分則表示數(shù)據(jù)由從機向主機傳送。
A表示應答, 表示非應答(高電平)。S表示起始信號,P表示終止信號。
b、主機在第一個字節(jié)后,立即由從機讀數(shù)據(jù)
c、在傳送過程中,當需要改變傳送方向時,起始信號和從機地址都被重復產生一次,但兩次讀/寫方向位正好反相。
5)IIC總線的尋址
I2C總線協(xié)議有明確的規(guī)定:采用7位的尋址字節(jié)(尋址字節(jié)是起始信號后的第一個字節(jié))。
(1)尋址字節(jié)的位定義
D7~D1位組成從機的地址。D0位是數(shù)據(jù)傳送方向位,為“0”時表示主機向從機寫數(shù)據(jù),為“1”時表示主機由從機讀數(shù)據(jù)。
主機發(fā)送地址時,總線上的每個從機都將這7位地址碼與自己的地址進行比較,如果相同,則認為自己正被主機尋址,根據(jù)R/位將自己確定為發(fā)送器或接收器。
從機的地址由固定部分和可編程部分組成。在一個系統(tǒng)中可能希望接入多個相同的從機,從機地址中可編程部分決定了可接入總線該類器件的最大數(shù)目。如一個從機的7位尋址位有4位是固定位,3位是可編程位,這時僅能尋址8個同樣的器件,即可以有8個同樣的器件接入到該I2C總線系統(tǒng)中。
(2)尋址字節(jié)中的特殊地址
其中高四位為器件類型識別符(即固定地址編號0000和1111,不同的芯片類型有不同的定義,EEPROM一般應為1010),接著三位為片選,最后一位為讀寫位,當為1時為讀操作,為0時為寫操作。
起始信號后的第一字節(jié)的8位為“0000 0000”時,稱為通用呼叫地址。通用呼叫地址的用意在第二字節(jié)中加以說明。
格式為:
第二字節(jié)為 06H時,所有能響應通用呼叫地址的從機器件復位,并由硬件裝入從機地址的可編程部分。能響應命令的從機器件復位時不拉低SDA和SCL線,以免堵塞總線。
第二字節(jié)為 04H時,所有能響應通用呼叫地址并通過硬件來定義其可編程地址的從機器件將鎖定地址中的可編程位,但不進行復位。
如果第二字節(jié)的方向位B為“1”,則這兩個字節(jié)命令稱為硬件通用呼叫命令。
在這第二字節(jié)的高7位說明自己的地址。接在總線上的智能器件,如單片機或其他微處理器能識別這個地址,并與之傳送數(shù)據(jù)。硬件主器件作為從機使用時,也用這個地址作為從機地址。
格式為:
在系統(tǒng)中另一種選擇可能是系統(tǒng)復位時硬件主機器件工作在從機接收器方式,這時由系統(tǒng)中的主機先告訴硬件主機器件數(shù)據(jù)應送往的從機器件地址,當硬件主機器件要發(fā)送數(shù)據(jù)時就可以直接向指定從機器件發(fā)送數(shù)據(jù)了。
(3)起始字節(jié)
起始字節(jié)是提供給沒有I2C總線接口的單片機查詢I2C總線時使用的特殊字節(jié)。
不具備I2C總線接口的單片機,則必須通過軟件不斷地檢測總線,以便及時地響應總線的請求。單片機的速度與硬件接口器件的速度就出現(xiàn)了較大的差別,為此,I2C總線上的數(shù)據(jù)傳送要由一個較長的起始過程加以引導。
引導過程由起始信號、起始字節(jié)、應答位、重復起始信號(Sr)組成。
請求訪問總線的主機發(fā)出起始信號后,發(fā)送起始字節(jié)(0000 0001),另一個單片機可以用一個比較低的速率采樣SDA線,直到檢測到起始字節(jié)中的7個“0”中的一個為止。在檢測到SDA線上的高電平后,單片機就可以用較高的采樣速率,以便尋找作為同步信號使用的第二個起始信號Sr。
80C51單片機I2C串行總線器件的接口1)總線數(shù)據(jù)傳送的模擬
主機可以采用不帶I2C總線接口的單片機,如80C51、AT89C2051等單片機,利用軟件實現(xiàn)I2C總線的數(shù)據(jù)傳送,即軟件與硬件結合的信號模擬。
(1)典型信號模擬
(2)典型信號模擬子程序
①起始信號
[backcolor=rgb(15, 25, 42) !important][size=1em]
[size=1em]01

[size=1em]02

[size=1em]03

[size=1em]04

[size=1em]05

[size=1em]06

[size=1em]07

[size=1em]08

[size=1em]09

[size=1em]10

[size=1em][size=1em]void T2CStart(void)
[size=1em]{
[size=1em]   SomeNop();
[size=1em]   SCL = 1;
[size=1em]   SomeNop();
[size=1em]   SDA = 0;
[size=1em]   SomeNop();
[size=1em]   SCL = 0;
[size=1em]   SomeNop();
[size=1em]}



②終止信號
[backcolor=rgb(15, 25, 42) !important][size=1em]
[size=1em]01

[size=1em]02

[size=1em]03

[size=1em]04

[size=1em]05

[size=1em]06

[size=1em]07

[size=1em]08

[size=1em]09

[size=1em]10

[size=1em][size=1em]void I2cStop(void)
[size=1em]{
[size=1em]   SDA = 0;
[size=1em]   SomeNop();
[size=1em]   SCL = 1;
[size=1em]   SomeNop();
[size=1em]   SDA = 1;
[size=1em]   SomeNop();
[size=1em]   SCL = 1;
[size=1em]}



本章沒有需要下載的資料
本章的內容到這里就結束了,藍橋杯中我們需要用到的IIC總線的器件有兩個一個是AT24C02另一個是PCF8591,一個是儲存芯片一個是AD轉換芯片,這兩個芯片的應用我們在后續(xù)的教程中也會進一步講解。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


回復

使用道具 舉報

ID:231500 發(fā)表于 2018-2-26 00:07 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(15)IIC總線驅動的編寫及注釋
后學我們將講到的AT24C02和PCF8591芯片都是使用的IIC總線協(xié)議,故本章末尾會將這兩個芯片需要使用到的一些函數(shù)一并引出,在后續(xù)章節(jié)進行詳細講解。
本章程序的注釋不多,希望大家多對照上一章的內容進行理解。
  1. #ifndef _IIC_H
  2. #define _IIC_H

  3. #include "stc15f2k60s2.h"
  4. #include "intrins.h"

  5. #define uchar unsigned char
  6. #define uint unsigned int

  7. // 總線引腳定義
  8. sbit SDA = P2^1; /* 數(shù)據(jù)線 */
  9. sbit SCL = P2^0; /* 時鐘線 */

  10. void Delay5us() //@11.0592MHz
  11. {
  12.    uchar i;
  13.    
  14.    _nop_();
  15.    i = 11;
  16.    while (--i);
  17. }

  18. void Delay10ms() //@11.0592MHz
  19. {
  20.    uchar i, j;

  21.    i = 108;
  22.    j = 145;
  23.    do
  24.    {
  25.       while (--j);
  26.    } while (--i);
  27. }

  28. // 總線啟動條件
  29. void IIC_Start(void)
  30. {
  31.    SDA = 1;
  32.    SCL = 1;
  33.    Delay5us();
  34.    SDA = 0;
  35.    Delay5us();
  36.    SCL = 0;
  37. }

  38. // 總線停止條件
  39. void IIC_Stop(void)
  40. {
  41.    SDA = 0;
  42.    SCL = 1;
  43.    Delay5us();
  44.    SDA = 1;
  45. }

  46. // 應答位控制
  47. void IIC_Ack(bit ackbit)
  48. {
  49.    if (ackbit)
  50.    {
  51.       SDA = 0;
  52.    }
  53.    else
  54.    {
  55.       SDA = 1;
  56.    }
  57.    Delay5us();
  58.    SCL = 1;
  59.    Delay5us();
  60.    SCL = 0;
  61.    SDA = 1;
  62.    Delay5us();
  63. }

  64. // 等待應答
  65. bit IIC_WaitAck(void)
  66. {
  67.    SDA = 1;
  68.    Delay5us();
  69.    SCL = 1;
  70.    Delay5us();
  71.    if (SDA)
  72.    {
  73.       SCL = 0;
  74.       IIC_Stop();
  75.       return 0;
  76.    }
  77.    else
  78.    {
  79.       SCL = 0;
  80.       return 1;
  81.    }
  82. }

  83. // 通過 I2C 總線發(fā)送數(shù)據(jù)
  84. void IIC_SendByte(uchar byt)
  85. {
  86.    uchar i;
  87.    for (i = 0;i < 8;i++)
  88.    {
  89.       if (byt & 0x80)
  90.       {
  91.          SDA = 1;
  92.       }
  93.       else
  94.       {
  95.          SDA = 0;
  96.       }
  97.       Delay5us();
  98.       SCL = 1;
  99.       byt <<= 1;
  100.       Delay5us();
  101.       SCL = 0;
  102.    }
  103. }

  104. // 從 I2C 總線上接收數(shù)據(jù)
  105. uchar IIC_RecByte(void)
  106. {
  107.    uchar da;
  108.    uchar i;
  109.    
  110.    for (i = 0;i < 8;i++)
  111.    {
  112.       SCL = 1;
  113.       Delay5us();
  114.       da <<= 1;
  115.       if (SDA)
  116.          da |= 0x01;
  117.       SCL = 0;
  118.       Delay5us();
  119.    }
  120.    return da;
  121. }

  122. //PCF8591初始化
  123. void ADC_Init(uchar chanel)
  124. {
  125.    IIC_Start();      //IIC啟動信號
  126.    IIC_SendByte(0x90);  //1001 000 0;選中該器件(前7位是地址,最后一位是R/~W,表示寫)
  127.    IIC_WaitAck();  //等待應答
  128.    IIC_SendByte(chanel);//通過IIC發(fā)送通道
  129.    IIC_WaitAck();  //等待應答
  130.    IIC_Stop();  //IIC停止信號
  131.    Delay10ms();      //等待10ms
  132. }

  133. //讀取PCF8591
  134. uchar ADC_Read()
  135. {
  136.    uchar temp;
  137.    IIC_Start();     //IIC啟動信號
  138.    IIC_SendByte(0x91); //1001 000 1;選中該器件(前7位是地址,最后一位是R/~W,表示讀)
  139.    IIC_WaitAck(); //等待應答
  140.    temp=IIC_RecByte(); //通過IIC讀取采集的值
  141.    IIC_Ack(0); //通過IIC發(fā)送應答
  142.    IIC_Stop(); //IIC停止信號
  143.    return temp;
  144. }

  145. void WriteByte_AT24C02(uchar add,uchar date)
  146. {
  147.    IIC_Start();
  148.    IIC_SendByte(0xa0);//發(fā)方式字1010 0000
  149.    IIC_WaitAck();
  150.    IIC_SendByte(add);
  151.    IIC_WaitAck();
  152.    IIC_SendByte(date);
  153.    IIC_WaitAck();
  154.    IIC_Stop();
  155.    Delay10ms();
  156. }

  157. uchar ReadByte_AT24C02(uchar add)
  158. {
  159.    uchar date;

  160.    IIC_Start();
  161.    IIC_SendByte(0xa0);//發(fā)方式字1010 0000
  162.    IIC_WaitAck();
  163.    IIC_SendByte(add);
  164.    IIC_WaitAck();

  165.    IIC_Start();
  166.    IIC_SendByte(0xa1);//發(fā)方式字1010 0001
  167.    IIC_WaitAck();
  168.    date = IIC_RecByte();
  169.    IIC_Ack(0);
  170.    IIC_Stop();
  171.    return date;
  172. }
復制代碼
本章資料下載見原文。

本章關于IIC總線的驅動程序就如上文所示,再有四章內容我們將AT24C02和PCF8591芯片的功能原理以及簡單的程序運用講完,該教材將暫停5天左右,最晚于3月五號繼續(xù)更新,講解歷年省賽真題內容。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog  http://www.bkoak.com


聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


回復

使用道具 舉報

ID:231500 發(fā)表于 2018-3-1 20:52 | 顯示全部樓層
【藍橋杯單片機設計與開發(fā)】(16)AT24C02串行E2PROM原理講解及程序編寫
EEPROM的使用,AT24C02,可以掉電依舊保存上一次操作的數(shù)據(jù),下次上電后接著運行。
需要注意兩個函數(shù),一個是寫進EEPROM里面保存,再次上電再從里面讀回來,其中寫函數(shù)需要指定AT24C02的地址以及需要寫入的數(shù)據(jù),讀函數(shù)要想取回寫進的數(shù)據(jù),需要從相同的地址里面讀,其中AT24C02的存儲地址是0x00,可以是其他地址,如0x02,但是讀和寫的地址必須一致由芯片資料及原理圖知EEPROM(AT24C02)的寫地址為0xa0;讀地址為0xa1。(讀寫函數(shù)見上章)
注意:讀數(shù)的時候讀出一個數(shù)之后發(fā)送一個應答信號,若ACK(0)表示還想繼續(xù)讀下一個字節(jié),若ACK(1);則不想再讀數(shù),讓EEPROM停止發(fā)送。
示例程序
  1. /* 2017.2.25 */
  2.    /* www.bkoak.com */
  3.    /* AT24C02讀寫例程 */

  4. #include "stc15f2k60s2.h"
  5. #include "IIC.h"

  6. uchar code tab[] =
  7. {0XC0,0XF9,0XA4,0XB0,0X99,0X92,
  8. 0X82,0XF8,0X80,0X90,0XBF,0XFF};
  9. uchar strtab[2];
  10. uchar buffer;

  11. void temp_to_display(uchar temp);
  12. void Timer1Init(void);

  13. void main()
  14. {
  15.    P2 = ((P2&0x1f)|0xa0);
  16.    P0 = 0x00;
  17.    P2 = ((P2&0x1f)|0xc0);
  18.    P0 = 0x00;

  19.    Timer1Init();
  20.    ET1 = 1;
  21.    EA = 1;
  22.    
  23.    WriteByte_AT24C02(0x00,15);

  24.    while(1)
  25.    {
  26.       buffer = ReadByte_AT24C02(0x00);
  27.       temp_to_display(buffer);
  28.    }
  29. }

  30. void temp_to_display(uchar temp)
  31. {
  32.    strtab[0] = tab[(temp / 100) % 10];
  33.    strtab[1] = tab[(temp / 10) % 10];
  34.    strtab[2] = tab[temp % 10];
  35. }

  36. void Timer1Init(void) //1毫秒@11.0592MHz
  37. {
  38.    AUXR |= 0x40; //定時器時鐘1T模式
  39.    TMOD &= 0x0F; //設置定時器模式
  40.    TL1 = 0x66; //設置定時初值
  41.    TH1 = 0xEA; //設置定時初值
  42.    TF1 = 0; //清除TF1標志
  43.    TR1 = 1; //定時器1開始計時
  44. }

  45. void Timer1_int() interrupt 3 using 0
  46. {
  47.    static uchar num;
  48.    TH1 = 0x66;
  49.    TL1 = 0xea;

  50.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  51.    {
  52.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  53.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  54.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  55.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  56.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  57.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  58.       default:break;
  59.    }
  60.    num++;
  61.    if (num == 3)
  62.       num = 0;
  63. }
復制代碼

【藍橋杯單片機設計與開發(fā)】(17)PCF8591 8位A/D和D/A轉換器轉換原理講解及程序編寫
這里我們只需要了解一下PCF8591的時序格式,只需根據(jù)時序格式發(fā)送地址字節(jié)和控制字節(jié)。
當使用AD轉換的時候需要在main函數(shù)開始時調用,該函數(shù)內部只需看這句代碼即可:i2c_sendbyte(0x03);ADC通道3,板上有4個模擬輸入口,分別為0,1,2,3;設置哪一個模擬輸入口就是根據(jù)這句代碼,0x03表示通道3,8位前6位不用管,都為0,最后兩位就是配置選擇哪一個通道的。
地址字節(jié),其中A2,A1,A0硬件已經接地,故都為0,最低位表示的是你要從IIC總線上讀數(shù)還是寫數(shù)據(jù),1表示讀,0表示寫,即讀數(shù)據(jù)發(fā)的地址是:0x91;寫數(shù)據(jù)發(fā)的地址是0x90。
控制字節(jié),由芯片資料知,控制字節(jié)有8位,有兩位固定是0,除了第0、1位需要自己設置,其他的我們都設為0,那些位都是一些具體的功能,我們暫時用不著,不用管先,第0、1位是模擬通道選擇,PCF8591上提供了4路模擬通道,根據(jù)需求進行選擇,如選擇通道3即發(fā)送控制字節(jié):0x03。
示例程序
  1. /* 2017.2.25 */
  2.    /* www.bkoak.com */
  3.    /* PCF8591AD例程 */

  4. #include "stc15f2k60s2.h"
  5. #include "IIC.h"

  6. uchar code tab[] =
  7. {0XC0,0XF9,0XA4,0XB0,0X99,0X92,
  8. 0X82,0XF8,0X80,0X90,0XBF,0XFF};
  9. uchar strtab[2];

  10. void temp_to_display(uchar temp);
  11. void Timer1Init(void);

  12. void main()
  13. {
  14.    P2 = ((P2&amp;0x1f)|0xa0);
  15.    P0 = 0x00;
  16.    P2 = ((P2&amp;0x1f)|0xc0);
  17.    P0 = 0x00;

  18.    Timer1Init();
  19.    ET1 = 1;
  20.    EA = 1;

  21.    ADC_Init(0x03);
  22.    while(1)
  23.    {
  24.       temp_to_display(ADC_Read());
  25.    }
  26. }

  27. void temp_to_display(uchar temp)
  28. {
  29.    strtab[0] = tab[(temp / 100) % 10];
  30.    strtab[1] = tab[(temp / 10) % 10];
  31.    strtab[2] = tab[temp % 10];
  32. }

  33. void Timer1Init(void) //1毫秒@11.0592MHz
  34. {
  35.    AUXR |= 0x40; //定時器時鐘1T模式
  36.    TMOD &= 0x0F; //設置定時器模式
  37.    TL1 = 0x66; //設置定時初值
  38.    TH1 = 0xEA; //設置定時初值
  39.    TF1 = 0; //清除TF1標志
  40.    TR1 = 1; //定時器1開始計時
  41. }

  42. void Timer1_int() interrupt 3 using 0
  43. {
  44.    static uchar num;
  45.    TH1 = 0x66;
  46.    TL1 = 0xea;

  47.    switch(num)//分別調用緩沖區(qū)的值進行掃描
  48.    {
  49.       case 0: P2 = ((P2&0x1f)|0xc0); P0 = 0x20;
  50.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  51.       case 1: P2 = ((P2&0x1f)|0xc0); P0 = 0x40;
  52.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  53.       case 2: P2 = ((P2&0x1f)|0xc0); P0 = 0x80;
  54.               P2 = ((P2&0x1f)|0xff); P0 = strtab[num];break;
  55.       default:break;
  56.    }
  57.    num++;
  58.    if (num == 3)
  59.       num = 0;
  60. }
復制代碼

本章資料下載地址見原文。
           希望接下來的幾天大家好好復習一下前面章節(jié)的內容,對比賽做好準備,3.5-3.15號之間為大家更新客觀題和省賽綜合題的內容。

本文采用 「CC BY-NC-SA 4.0」創(chuàng)作共享協(xié)議,轉載請標注以下信息:
原文出處:Bkoak’s blog  http://www.bkoak.com

聯(lián)系博主
郵箱:wjf418224424@aliyun.com
更多資訊關注公眾號:智術靈慧(zslh_dyh)
QQ交流群:693211073


回復

使用道具 舉報

ID:231500 發(fā)表于 2018-3-1 20:53 | 顯示全部樓層
藍橋杯單片機開發(fā)省賽基礎部分就到此結束了,后面會開新帖進行客觀題和歷年省賽的真題及模擬題的講解,有問題可以進群或郵箱留言。
回復

使用道具 舉報

ID:220062 發(fā)表于 2018-3-2 10:49 | 顯示全部樓層
冒泡看一下
回復

使用道具 舉報

ID:286874 發(fā)表于 2018-3-2 11:09 | 顯示全部樓層
謝謝樓主
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-3-6 18:42 | 顯示全部樓層
回復

使用道具 舉報

ID:231500 發(fā)表于 2018-10-11 22:43 | 顯示全部樓層
新一年的比賽報名已經開始,我會繼續(xù)更新一些教程,把往年的省賽國賽題目都作出歷程給大家,,同時后面還有一個AD18的教學貼和開源POV玩具的制作貼會慢慢更新,有興趣的朋友可以關注公眾號或者加入交流群,大家一起交流學習。
回復

使用道具 舉報

ID:294964 發(fā)表于 2018-12-4 17:12 | 顯示全部樓層
干貨,支持。。!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表