一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Zigbee之旅(六):幾個重要的CC2430基礎(chǔ)實驗——ADC單次采樣(轉(zhuǎn))

 小酒館II 2012-07-28

Zigbee之旅(六):幾個重要的CC2430基礎(chǔ)實驗——ADC單次采樣(轉(zhuǎn))

 一、承上啟下

  在無線傳感器網(wǎng)絡(luò)中,很重要的一項就是將傳感器的模擬值轉(zhuǎn)換成數(shù)字量,以便于傳輸和處理。而ADC(Analog-to-Digital Converter)正是用來完成這種轉(zhuǎn)換的。

  上一節(jié),我們介紹了CC2430與PC之間的串口通信。CC2430內(nèi)部已嵌入一個溫度傳感器,本節(jié)將在上一節(jié)的基礎(chǔ)上,實現(xiàn)一個簡單的關(guān)于片內(nèi)溫度監(jiān)測的小實驗:利用ADC將片內(nèi)溫度傳感器的電壓值轉(zhuǎn)換成數(shù)字量,利用公式計算出溫度值,然后通過串口將溫度值傳送到PC上并顯示出來。

  二、ADC單次采樣

 ?。?)實驗簡介

  利用ADC轉(zhuǎn)換CC2430片內(nèi)溫度傳感器的溫度值,通過串口將溫度值發(fā)送到PC并顯示出來。

  (2)程序流程圖

 ?。?)實驗源碼及剖析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
    實驗說明:片內(nèi)溫度采集實驗,通過串口0將數(shù)據(jù)發(fā)送到PC機
*/
  
#include <ioCC2430.h>
  
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
  
/*32M晶振初始化
-------------------------------------------------------*/
void xtal_init(void)
{
  SLEEP &= ~0x04;             //都上電
  while(!(SLEEP & 0x40));     //晶體振蕩器開啟且穩(wěn)定
  CLKCON &= ~0x47;          //選擇32MHz 晶體振蕩器
  SLEEP |= 0x04;
}
  
/*LED燈初始化
-------------------------------------------------------*/
void led_init(void)
{
  P1SEL  = 0x00;          //P1為普通 I/O 口
  P1DIR |= 0x0F;          //P1.0 P1.1 P1.2 P1.3 輸出
 
  led1 = 1;
  led2 = 1;
  led3 = 1;
  led4 = 1;
}
  
/*UART0初始化
-------------------------------------------------------*/
void  Uart0Init(unsigned char StopBits,unsigned char Parity)
{
   P0SEL |=  0x0C;                  //初始化UART0端口
   PERCFG&= ~0x01;                  //選擇UART0為可選位置一
   U0CSR = 0xC0;                    //設(shè)置為UART模式,而且使能接受器
   U0GCR = 11;
   U0BAUD = 216;                    //設(shè)置UART0波特率為115200bps
   U0UCR |= StopBits|Parity;        //設(shè)置停止位與奇偶校驗
}
  
/*UART0發(fā)送字符
-------------------------------------------------------*/
void  Uart0Send(unsigned char data)
{
  while(U0CSR&0x01);    //等待UART空閑時發(fā)送數(shù)據(jù)
  U0DBUF = data;
}
  
/*UART0發(fā)送字符串
-------------------------------------------------------*/
void Uart0SendString(unsigned char *s)
{
  while(*s != 0)
    Uart0Send(*s++);
}
  
/*UART0接收數(shù)據(jù)
-------------------------------------------------------*/
unsigned char Uart0Receive(void)
{
  unsigned char data;
  while(!(U0CSR&0x04)); //查詢是否收到數(shù)據(jù),否則繼續(xù)等待
  data=U0DBUF;
  return data;
}
  
/*延時函數(shù)
-------------------------------------------------------*/
void Delay(unsigned int n)
{
  unsigned int i;
  for(i=0;i<n;i++);
  for(i=0;i<n;i++);
  for(i=0;i<n;i++);
  for(i=0;i<n;i++);
  for(i=0;i<n;i++);
}
  
/*得到實際溫度值
-------------------------------------------------------*/
float getTemperature(void)
{
  unsigned int  value;
  
  ADCCON3  = (0x3E);                  //選擇1.25V為參考電壓;14位分辨率;對片內(nèi)溫度傳感器采樣
  
  ADCCON1 |= 0x30;                    //選擇ADC的啟動模式為手動
  ADCCON1 |= 0x40;                    //啟動AD轉(zhuǎn)化           
  
  while(!(ADCCON1 & 0x80));           //等待ADC轉(zhuǎn)化結(jié)束
  
  value =  ADCL >> 2;
  value |= (ADCH << 6);               //取得最終轉(zhuǎn)化結(jié)果,存入value中
 
  return value*0.06229-311.43;        //根據(jù)公式計算出溫度值
}
  
/*主函數(shù)
-------------------------------------------------------*/
void main(void)
{
  char i;
  float avgTemp;
  unsigned char output[]="";
      
  xtal_init();
  led_init();
 
  led1 = 0;
  
  Uart0Init(0x00, 0x00);   //初始化串口:無奇偶校驗,停止位為1位
  
  Uart0SendString("Hello CC2430 - TempSensor!\r\n");
  
  while(1)
  {
    led1 = 0;
    avgTemp = 0;
    for(i = 0 ; i < 64 ; i++)
    {
      avgTemp += getTemperature();
      avgTemp = avgTemp/2;             //每采樣1次,取1次平均值
    }
  
    output[0] = (unsigned char)(avgTemp)/10 + 48;          //十位
    output[1] = (unsigned char)(avgTemp)%10 + 48;          //個位
    output[2] = '.';                                       //小數(shù)點
    output[3] = (unsigned char)(avgTemp*10)%10+48;         //十分位
    output[4] = (unsigned char)(avgTemp*100)%10+48;        //百分位
    output[5] = '\0';                                      //字符串結(jié)束符
  
    Uart0SendString(output);
    Uart0SendString("℃\n");
    led1 = 1;                          //LED熄滅,表示轉(zhuǎn)換結(jié)束,
  
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
    Delay(20000);
  }
}

關(guān)于串口通信的代碼內(nèi)容,請參考上一節(jié),在此不解釋~

  ADC一般涉及到6個SFR:

 

ADCCON1 用于ADC通用控制,包括轉(zhuǎn)換結(jié)束標志、ADC觸發(fā)方式、隨機數(shù)發(fā)生器
ADCCON2 用于連續(xù)ADC轉(zhuǎn)換的配置(本實驗不涉及連續(xù)ADC轉(zhuǎn)換,故不使用此SFR)
ADCCON3 用于單次ADC轉(zhuǎn)換的配置,包括選擇參考電壓、分辨率、轉(zhuǎn)換源
ADCH[7:0] ADC轉(zhuǎn)換結(jié)果的高位,即ADC[13:6]
ADCL[7:2] ADC轉(zhuǎn)換結(jié)果的低位,即ADC[5:0]
ADCCFG 選擇 P0.0~P0.7 作為ADC輸入的 AIN0~AIN7(由于本次試驗選擇片內(nèi)溫度傳感器作為轉(zhuǎn)換源,不涉及AIN0~AIN7,故不使用此SFR) 

 

 ?。ㄗⅲ阂陨蟂FR的具體內(nèi)容請參考CC2430中文手冊)

  接下來,我們來重點關(guān)注一下 getTempurature 函數(shù),它是獲取溫度值的關(guān)鍵:

 ?。?)首先配置ADC單次采樣:令 ADCCON3=0x3E,選擇1.25V為系統(tǒng)電壓,選擇14位分辨率,選擇CC2430片內(nèi)溫度傳感器作為ADC轉(zhuǎn)換源

 ?。?)然后令 ADCCON1 |= 0x30,設(shè)置ADC觸發(fā)方式為手動(即當ADCCON.6=1時,啟動ADC轉(zhuǎn)換)

 ?。?)接著令  ADCCON1 |= 0x40,啟動ADC單次轉(zhuǎn)換

 ?。?)使用語句 while(!(ADCCON1 & 0x80))  等待ADC轉(zhuǎn)換的結(jié)束

 ?。?)轉(zhuǎn)換結(jié)果存放在ADCH[7:0](高8位),ADCH[7:2](低6位),通過:

    value =  ADCL >> 2;     value |= (ADCH << 6);      

  將轉(zhuǎn)換結(jié)果存進 value 中

 ?。?)最后利用公式 temperature= value*0.06229-311.43 ,計算出溫度值并返回即可

  CC2430 小貼士

  你一定會對最后一個公式感到莫名其妙,為什么是一次函數(shù)?為什么其斜率為0.06229,其截距為211.43?OK,下面解惑之:

  此溫度傳感器是位于CC2430片內(nèi)的,所以必然可以在其手冊中找到其介紹。果不其然,我在 電氣規(guī)范 這一節(jié)中找到了相關(guān)內(nèi)容,現(xiàn)截圖如下:

  查看原圖(大圖)

  此表是描述溫度傳感器的溫度(℃)與輸出電壓(V)的關(guān)系。

  首先看第二個紅框處:溫度系數(shù)?!跋禂?shù)”?是不是有點感覺?然后再看其單位:mV/℃,你就會恍然大悟,原來溫度與電壓的關(guān)系是線性的啊~ 即有:

  其中V為輸出電壓值,T為溫度值,2.45為斜率。下面就要確定截距b了。

  乍一看,我們會在第一個紅框處發(fā)現(xiàn)0℃時的電壓為743mV,那么b就等于743?不然,繼續(xù)往下看,你會發(fā)現(xiàn)其絕對誤差達到了8℃之多!然后往右看,我們會發(fā)現(xiàn)它已經(jīng)提供了最適合的截距,即:b=763,因此有如下公式:

  OK,現(xiàn)在我們已經(jīng)有了溫度傳感器的 輸入溫度T 和 輸出電壓V 的關(guān)系,接下來必須找到ADC的 輸入電壓V 與 輸出值N(即14位的轉(zhuǎn)換結(jié)果)的關(guān)系,才可最終找到N和T的轉(zhuǎn)換公式。

  轉(zhuǎn)換結(jié)果N是14位的,當N=11 1111 1111 1111(二進制)時,輸出電壓應(yīng)為最大值(即參考電壓1.25V)。因此我們有下面的比例關(guān)系:

  (注:由于14位的輸出結(jié)果是2進制的補碼,因此第14位為符號位。所以從絕對值的角度來說,有效值只有13位,因此是2的13次方)   

  結(jié)合兩式,可導(dǎo)出T與N的關(guān)系:

  OVER~

  最后,稍微提一下為什么每次采樣需要進行64循環(huán)。因為傳感器在測定溫度時,難免會受到干擾或者隨機性的error,其得到的數(shù)據(jù)有時候會很夸張(比如說忽然出現(xiàn)10℃的變動,然后又瞬間回復(fù)正常。但我們知道溫度的變化是一個積分的過程,很少會出現(xiàn)那種在瞬間產(chǎn)生大幅度跳躍的情況)。因此我們采用了取平均值的方法來減少此類誤差。

  (4)實驗結(jié)果

  首先打開串口調(diào)試工具,然后下載程序并啟動,就會出現(xiàn)如下畫面:

  片內(nèi)溫度大概在14.5℃左右。筆者用身體感受寢室的室溫,大概在10℃多一點。芯片內(nèi)部多少要發(fā)點熱,所以14℃基本正常啦~

  到此,實驗結(jié)束。    

  三、結(jié)語

  本篇介紹了ADC單次采樣的實現(xiàn)。下一節(jié),我們來介紹一種數(shù)據(jù)傳輸模式 DMA(direct memory access),即“直接內(nèi)存存取”。ADC/UART/RF收發(fā)器等外設(shè)單元和存儲器件之間,可以直接在“DMA控制器”的控制下交換數(shù)據(jù)而幾乎不需要CPU的干預(yù),因此可大大提高了系統(tǒng)的整體效率。

0
0
(請您對文章做出評價)
博主前一篇:Zigbee之旅(五):幾個重要的CC2430基礎(chǔ)實驗——串口通信(轉(zhuǎn))
博主后一篇:Zigbee之旅(七):幾個重要的CC2430基礎(chǔ)實驗——DMA傳輸(轉(zhuǎn))

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    成人日韩在线播放视频| 少妇肥臀一区二区三区| 日韩18一区二区三区| 亚洲精品国产福利在线| 欧美视频在线观看一区| 成人午夜爽爽爽免费视频| 国产激情一区二区三区不卡| 国产不卡在线免费观看视频| 91精品蜜臀一区二区三区| 亚洲国产婷婷六月丁香| 日韩精品毛片视频免费看| 国产二级一级内射视频播放| 99国产成人免费一区二区| 国产91麻豆精品成人区| 中文字幕日韩精品人一妻| 国产一区二区久久综合| 久久精品免费视看国产成人| 欧美熟妇一区二区在线| 欧美自拍系列精品在线| 国产精品午夜福利免费阅读| 日本人妻中出在线观看| 久久精品偷拍视频观看| 日韩性生活片免费观看| 五月婷婷综合缴情六月| 国产高清在线不卡一区| 亚洲欧美日本国产有色| 欧美一级内射一色桃子| 欧美日韩一区二区综合| 国产一区日韩二区欧美| 久久免费精品拍拍一区二区 | 亚洲天堂精品在线视频| 亚洲精品一区二区三区免| 中文字幕人妻日本一区二区| 亚洲欧美精品伊人久久| 国内女人精品一区二区三区| 91福利免费一区二区三区| 国产精品刮毛视频不卡| 欧美日韩国产精品第五页| 99热在线精品视频观看| 91欧美视频在线观看免费| 五月婷婷缴情七月丁香|