目錄
前言
1. 簡介
1.1 UART口與COM口
1.2 UART口的特征
1.3 UART口兼容COM口
2.使用場景
3.作業模式(僅了解即可)
3.1 單工模式(Simplex)
3.2 半雙工模式(Half duplex)
3.3 全雙工模式(Full duplex)
4.RS232串口通信標準和介面定義
4.1外觀
4.2物理層
4.3協議層
4.3.1 波特率
4.3.2 通訊的起始位和停止位
4.3.3 資料位
4.3.4 資料校驗
4.3.5 資料傳輸率
5. USB轉RS232串口電路
6.演示RS232串口協議
6.1 STM32F103芯片
6.2 下位機開發板介紹
6.2.1 下位機開發板中STM32F103ZET芯片引腳分配圖
6.2.2 下位機串口原理圖
6.3 下位機串口通信代碼實作
6.4 上位機串口通信代碼實作
6.5 USB轉RS232串口驅動安裝
6.6 效果展示
7.應用:讀取溫度傳感器(DS18B20)的傳感值
7.1 DS18B20溫度傳感器介紹
7.2 下位機開發板上DS18B20原理圖
7.3 下位機實作讀取DS18B20傳感器溫度值
7.4 實作上位機與下位機通信的串口指令
7.5 上位機溫度曲線顯示功能實作
7.6 效果展示
參考
前言
本文簡要介紹串口概念、物理介面、通信協議,最后借助串口從下位機將溫度傳感器的實測溫度上傳至上位機進行展示,本文不以詳細教授嵌入式編程技巧,僅展示串口通信和嵌入式編程的大概流程,僅作為“科普”目的,閱讀此文無需具備嵌入編程經驗,感興趣即可,
1. 簡介
串行通信埠( cluster communication port ),簡稱串口,即COM口,串行通信是指資料一位一位地順序傳送,其特點是通信線路簡單,只要一對傳輸線就可以實作雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本,但傳送速度較慢(后文會計算其傳輸速度),
1.1 UART口與COM口
嵌入式里面說的串口,一般是指UART(Universal Asynchronous Receiver/Transmitter,通用異步收發傳輸器)口, 但是我們經常搞不清楚UART口和COM口的區別, 實際上UART、COM指的物理硬體介面形式,
UART有4個引腳(VCC, GND, RX, TX), 用的TTL電平, 低電平為0(0V),高電平為1(3.3V或以上),如圖1-1-1所示,
COM口是臺式機上面常用的介面(圖1-1-2),9個引腳, 用的RS-232標準電平, 使用負邏輯電平,定義+3 ~ +15V為低電平,而-15 ~ -3V為高電平,
1.2 UART口的特征
一般uart控制器在嵌入式系統里面都做在cpu一起,像飛思卡爾的IMX6芯片、意法半導體的STM32芯片就是這樣,有多個uart控制器,
UART引腳介紹(COM口有9個引腳,但是常用的也是下面這幾個):
VCC:供電引腳,一般是3.3v,在我們的板子上沒有過電保護,這個引腳一般不接更安全
GND:接地引腳,有的時候rx接受資料有問題,就要接上這個引腳,一般也可不接
RX:接收資料引腳
TX:發送資料引腳
1.3 UART口兼容COM口
由于UART口的VCC、GND、RX、RT引腳與COM口的這幾個引腳具有一樣的用途和功能,而絕大多數COM口通信中也僅需要使用這四個引腳,因此在很多場景下UART口可以作為COM口的兼容口使用,
2.使用場景
串行介面(COM口)是一種可以將接受來自CPU的并行資料字符轉換為連續的串行資料流發送出去,同時可將接受的串行資料流轉換為并行的資料字符供給CPU的器件,
串口是計算機上一種非常通用的設備通信協議,大多數計算機(不包括筆記本電腦)包含兩個基于RS-232的串口,串口同時也是儀器儀表設備通用的通信協議,同時,串口通信協議也可以用于獲取遠程采集設備的資料,
RS-232(ANSI/EIA-232標準)是IBM-PC及其兼容機上的串行連接標準,可用于許多用途,比如連接滑鼠、列印機或者Modem(調制解調器),同時也可以接工業儀器儀表,RS-232只限于PC串口和設備間點對點的通信,RS-232串口通信最遠距離是50英尺(15.24米),
3.作業模式(僅了解即可)
串行通信的基礎是單線傳輸,資料通常是在兩個站點之間進行傳輸,按照資料流的方向分為3種傳輸模式:
3.1 單工模式(Simplex)
單工模式的資料是單向的,通訊雙方一方為發送端,另一方則固定為接收端,資訊只能沿一個方向傳輸,使用一根資料線,例如收音機,只能接收發射塔給它的資料,并不能給發射塔發資料,
3.2 半雙工模式(Half duplex)
半雙工模式是指通訊雙方都具有發送器和接收器,雙方既可以發射也可以接收,但是接收和發射不能同時進行,半雙工一般用在兩個方向都傳輸資料的場合,例如對講機,
3.3 全雙工模式(Full duplex)
全雙工資料通訊分別由兩根可以在兩個不同的站點同時發送和接收的傳輸線進行傳輸資料,通訊雙方能在同一時刻進行發送和接收操作,
全雙工模式下,每一端都有發送器和接收器,有兩條傳輸線可以在互動式應用場合中使用,資訊傳輸效率高,例如手機,
此文我們研究的RS232串口標準通信就可以作業在全雙工通信模式下,因其將資料傳輸和接收采用獨立的2根線實作,因此可以同時發送和接收資料,接下來將詳細介紹RS232串口標準,
4.RS232串口通信標準和介面定義
4.1外觀
4.2物理層
這里講解RS-232標準,RS-232標準主要規定了信號的用途,通訊介面以及信號的電平標準,
使用RS-232標準串口的設備間通信結構圖如下:
兩個通訊設備的“DB9介面”之間用串口線建立起連接,串口線中使用RS-232標準傳輸資料信號,由于RS-232電平標準的信號不能直接被控制器直接識別,所以信號需要經過一個“電平轉換芯片”轉換成控制器能識別的“TTL標準”電平[參看 表4-2-1]信號,
RS232通信使用的電平標準詳細表如下:
常見的電子電路中常用TTL的電平標準,理想狀態下使用5V表示二進制邏輯1,使用0V表示二進制邏輯0,為了增加串口通訊的遠距離傳輸及抗干擾能力,它使用-15V表示邏輯1,+15V表示邏輯0,
其中接線口以針式引出信號線的稱為公頭(圖 4-1-1 右側),以孔式引出信號線的稱為母頭(圖 4-1-1 左側),
DB9 介面中的公頭及母頭的各個引腳的標準信號線接法:
RS-232的每一個引腳都有它的作用,也有信號流動方向,原先的RS-232是用來連接調制解調器[注:俗稱“貓”,Modem,是Modulator(調制器)與Demodulator(解調器)的簡稱],因此它的引腳位意義通常也和調制解調器傳輸相關,隨著行業發展,RS-232標準介面被用到更多的設備上,
從功能上來看,全部信號線分為3類:資料線(TXD、RXD)、地線(GND)和聯絡控制線(DSR、DTR、RI、DCD、RTS、CTS)
兩個通訊設備之間的地電位可能不一樣,這會影響收發雙方的電平信號,所以兩個串口設備之間必須要使用地線連接,即共地,
串口線中的聯絡控制線使用邏輯1表示信號有效,邏輯0表示信號無效,例如,當計算機端控制DTR信號線為邏輯1時,其目的是告知遠端的調制解調器本機已準備好接收資料,0表示還沒準備就緒,
在目前的其它工業控制使用的串口通訊中,一般只使用RXD、TXD以及GND三條信號線,直接傳輸資料信號,RTS、CTS等聯絡控制線被裁剪掉,
4.3協議層
根據通訊的資料同步方式,可分為同步和異步兩種,根據通訊程序中是否使用到時鐘信號進行區分,
在同步通信中,收發設備上方會使用一根信號線傳輸信號,在時鐘信號的驅動下雙方進行協調,同步資料,例如,通訊中通常雙方會統一規定在時鐘信號的上升沿或者下降沿對資料線進行采樣,
在異步通信中,不使用時鐘信號進行資料同步,它們直接在資料信號中穿插一些用于同步的信號位,或者將主題資料進行打包,以資料幀的格式傳輸資料,通訊中還需要雙方規約好資料的傳輸速率等,以便更好地同步,
兩種同步方式優劣:在同步通訊中,資料信號所傳輸的內容絕大部分是有效資料,而異步通訊中會則會包含資料幀的各種識別符號,所以同步通訊效率高,但是同步通訊雙方的時鐘允許誤差小,稍稍時鐘出錯就可能導致資料錯亂,異步通訊雙方的時鐘允許誤差較大,
本文講解常用的“異步通信”資料同步方式,
串口通訊的資料包由發送設備通過自身的TXD介面傳輸到接收設備的RXD介面,通訊雙方的資料包格式要規約一致才能正常收發資料,串口通訊協議層中,規定了資料包的內容,它由起始位、主體資料位、校驗位以及停止位組成,如圖4-3-1所示,
4.3.1 波特率
講波特率之前首先了解一下通信速率,
通信速率通常是以位元率來表示,即每秒鐘傳輸的二進制位數,單位為位元每秒(bit/s),容易和位元率混淆的概念是“波特率”,它表示每秒傳輸了多少碼元,
碼元是通信信號調制的概念,時間間隔相同的符號來表示一個二進制數字,這樣的信號就稱為碼元,如常見的通信傳輸中,用0V表示數字0,5V表示數字1,那么一個碼元可以表示兩種狀態0和1,所以一個碼元等于一個二進制位元位,此時波特率的大小與位元率一致;若傳輸中,有0V、2V、4V和6V分別表示00、01、10、11,那么每個碼元可以表示四種狀態,兩個二進制位元位,所以碼元數是二進制位元位數的一半,這個時候的波特率為位元率的一半,因為很多常見的通信中一個碼元都是表示兩種狀態,人們常常直接以波特率來表示位元率,其實二者是有區別的,而RS232串口通信中,一個碼元等于一個二進制位,
異步通信由于沒有時鐘信號(DB9介面[RS232標準口的另一種稱呼]沒有信號線),所以兩個通信設備需要規約好波特率,即每個碼元的長度,以便對信號進行解碼,圖 4-3-1中一個矩形表示一個碼元,常見的波特率為4800,9600,115200,921600,
4.3.2 通訊的起始位和停止位
串口通訊的一個資料包從起始信號開始,直到停止信號結束,資料包的起始信號由一個邏輯0的資料位表示,而資料包的停止信號可由0.5、1、1.5或2個邏輯1的資料位表示,只要雙方約定一致即可,圖 4-3-1中約定起始位和停止位都是1個邏輯1的資料位表示,
4.3.3 資料位
在資料包的起始位之后緊接著的就是要傳輸的主體資料內容,也稱為有效資料,有效資料的長度常被約定為5、6、7 或8 位長,圖 4-3-1中的D0~D7,
4.3.4 資料校驗
在有效資料之后,有一個可選的資料校驗位,由于資料通信相對更容易受到外部干擾導致傳輸資料出現偏差,可以在傳輸程序加上校驗位來解決這個問題,校驗方法有奇校驗(odd)、偶校驗(even)、0 校驗(space)、1 校驗(mark)以及無校驗(noparity),
奇校驗:要求有效資料和校驗位中“1”的個數為奇數
偶校驗:與奇校驗要求剛好相反,要求幀資料和校驗位中“1”的個數為偶數
0/1校驗:不管有效資料中的內容是什么,校驗位總為0或者1
4.3.5 資料傳輸率
由圖4-3-1可以計算出一個“字符幀”的有效資料比率,一個字符幀由4部分組成:
資料位:D0~D7,占據8位
起始位:1位
奇偶校驗位:1位
停止位:1位
即一個字符幀一共有11位,那么“一個字符幀的有效資料傳輸比率= 8 / 11”,
在RS232串口通信中,一個碼元等于一個二進制位,即此時“波特率=位元率”,假設在某次資料傳輸程序中,字符幀連續傳輸,無空閑,則常用波特下的資料傳輸比率如下:
波特率4800,換算位元率即 4800bps: 有效資料傳輸率 = 4800 bps*( 8/11) = 3490 bps = 3490 bps / 8 = 436 B/s
波特率9600,換算位元率即 9600bps: 有效資料傳輸率 = 9600 bps*( 8/11) = 6981 bps = 6981 bps / 8 = 872 B/s
波特率115200,換算位元率即 115200bps: 有效資料傳輸率 = 115200 bps*( 8/11) = 83781 bps = 83781 bps / 8 = 10472 B/s
波特率921600,換算位元率即 921600bps: 有效資料傳輸率 = 921600 bps*( 8/11) = 670254 bps = 670254 bps / 8 = 83781 B/s
可見RS232串口傳輸速率相比以太網的確慢很多,因此不適合用于大資料傳輸場景,適合傳輸控制信號和小資料量,
5. USB轉RS232串口電路
隨著USB介面及其協議的普及,串口也逐漸退出了公眾視野,僅存于某些特定設備行業中,很多個人電腦已經不再有RS232串口硬體介面,如果需要使用RS232串口可以通過USB介面轉RS232串口線(如圖 5-1)來連接串口設備,
由于USB介面使用4根線(如圖 5-2),而且USB協議與RS232使用的9根線及其協議完全不一樣,因此需要一個USB轉RS232的電路(如圖 5-3)完成協議的轉換,
6.演示RS232串口協議
本節將介紹如何基于STM(意法半導體)設計的STM32F103芯片(基于ARM Cotex-M3核心)演示RS232串口通信,STM32F103芯片內部已經實作了RS232標準的串口協議,接下來將詳細介紹,
6.1 STM32F103芯片
6.2 下位機開發板介紹
本文我們僅關注STM32F103ZET芯片(圖6-2-1中心的那塊芯片)、RS232串口、DS18B20溫度傳感器,
6.2.1 下位機開發板中STM32F103ZET芯片引腳分配圖
6.2.2 下位機串口原理圖
6.3 下位機串口通信代碼實作
初始化串口配置
/****************************************************************************
* Function Name : USART1_Config
* Description : Configurates the USART1.
* Input : baudRate:波特率
* Output : None
* Return : None
****************************************************************************/
void USART1_Config(uint16_t baudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* 打開RCC時鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 設定TXD的GPIO引數 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //串口輸出PA9
/* 初始化串口輸入IO */
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 設定RXD的GPIO引數 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模擬輸入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //串口輸入PA10
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 設定USART的引數 */
USART_InitStructure.USART_BaudRate = baudRate; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //資料長8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無效驗
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//使能硬體流
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //開啟發送和接受模式
/* 初始化USART1 */
USART_Init(USART1, &USART_InitStructure);
/* 使能USART1 */
USART_Cmd(USART1, ENABLE);
#ifdef USE_USART1RX_INTERRUPT
USART1_NVIC_RxConfig();
USART_ITConfig(USART1, USART_IT_RXNE ,ENABLE);
#endif
}
實作串口資料接收函式:串口的資料接收是通過硬體中斷(USART1中斷)發生時,呼叫中斷回應函式USART1_IRQHandler實作
/****************************************************************************
* Function Name : USART1_NVIC_RxConfig
* Description : 設定接收中斷的中斷等級,并打開總中斷
* Input : None
* Output : None
* Return : None
****************************************************************************/
void USART1_NVIC_RxConfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 設定NVIC引數 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優先級為0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //回應優先級為0
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //打開USART1的全域中斷
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能,
NVIC_Init(&NVIC_InitStructure);
}
/****************************************************************************
* Function Name : USART1_IRQHandler
* Description : 串口1的中斷函式
* Input : None
* Output : None
* Return : None
****************************************************************************/
uint8_t USART1_RX_Buff[64], USART1_RX_State;
void USART1_IRQHandler (void)
{
uint8_t dat;
/* 接收中斷(接收到的資料必須是0x0D 0x0A結尾(即回車))表示接收結束 */
if(USART_GetITStatus(USART1, USART_IT_RXNE))
{
dat = USART_ReceiveData(USART1);
/* 沒接收完,使用USART1_RX_State的最高位作結束標識 */
if(((USART1_RX_State & 0x80) == 0) && ((USART1_RX_State & 0x3F) < 63))
{
/* 已經接收到0x0D,使用USART1_RX_State的第6位(從0位開始)作接收到0x0D的標識 */
if(USART1_RX_State & 0x40)
{
if(dat == 0x0A) //第二個位元組接收到0x0A接收結束
{
USART1_RX_State |= 0x80;
USART1_RX_Buff[USART1_RX_State & 0x3F] = 0;
}
else
{
USART1_RX_State = 0;
}
}
else
{
if(dat == 0x0D) //接收到0x0D,標識USART1_RX_State的第6位(從0位開始)
{
USART1_RX_State |= 0x40;
}
else
{
USART1_RX_Buff[USART1_RX_State & 0x3F] = dat;
USART1_RX_State++;
}
}
}
}
}
實作串口資料發送函式
/****************************************************************************
* Function Name : USART1_SetWord
* Description : 通過串口1發送字串.
* Input : None
* Output : None
* Return : None
****************************************************************************/
void USART1_SendWord(uint8_t *wd)
{
while(*wd) //檢測是否發送資料是否為空
{
USART_SendData(USART1, *wd);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); //等待發送完畢
wd++;
}
}
// 串口資料發送函式
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
/* Transmit Data */
USARTx->DR = (Data & (uint16_t)0x01FF);
}
6.4 上位機串口通信代碼實作
上位機服務程式采用Qt庫(C++ GUI庫以及框架)實作,
創建串口通信物件(QSerialPort類實作了串口通信客戶端功能)
serial = new QSerialPort(this);
初始化串口通信引數
void MainWindow::openSerialPort()
{
SettingsDialog::Settings p = settings->settings();
serial->setPortName(p.name);
serial->setBaudRate(p.baudRate);
serial->setDataBits(/*p.dataBits*/QSerialPort::Data8);
serial->setParity(/*p.parity*/QSerialPort::NoParity);
serial->setStopBits(/*p.stopBits*/QSerialPort::OneStop);
serial->setFlowControl(/*p.flowControl*/QSerialPort::NoFlowControl);
if (serial->open(QIODevice::ReadWrite)) {
console->setEnabled(true);
console->setLocalEchoEnabled(p.localEchoEnabled);
ui->actionConnect->setEnabled(false);
ui->actionDisconnect->setEnabled(true);
ui->actionConfigure->setEnabled(false);
showStatusMessage(tr("Connected to %1 : %2, %3, %4, %5, %6")
.arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits)
.arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl));
} else {
QMessageBox::critical(this, tr("Error"), serial->errorString());
showStatusMessage(tr("Open error"));
}
}
串口讀寫
void MainWindow::readData()
{
QByteArray data = serial->readAll();
}
void MainWindow::writeData(const QByteArray &data)
{
serial->write(data);
}
6.5 USB轉RS232串口驅動安裝
如果你使用的USB轉RS232串口線是非通用型,則需要到你所購買此線的廠家官網下載對應驅動,然后安裝到作業系統,例如我用的是“優越者Y-105系列USB轉串口線”,則需要在其官網下載“PL2303u2c_veryhuo.com.rar”驅動(如圖6-5-1),然后安裝到作業系統中:
安裝成功后,使用此USB轉RS232串口線接下位機,Windows“設備管理器”中的“埠(COM和LPT)”節點(如圖6-5-2)下即會出現如圖6-5-3所示的COM設備(COM設備節點是從1編號,如COM1、COM7)
如果你購買的USB轉RS232串口線是通用型(CH340\CH341),則無需安裝驅動,Windows系統直接支持,即插即用!如圖6-5-4所示
6.6 效果展示
7.應用:讀取溫度傳感器(DS18B20)的傳感值
7.1 DS18B20溫度傳感器介紹
翻譯圖 7-1-1中DS18B20的產品特性介紹:
特征
% 獨特的1-Wire(1線)介面僅需一個埠引腳即可進行通信
% 多點功能簡化了分布式溫度感測應用
% 無需外部組件
% 可以通過資料線供電, 電源范圍為3.0V至5.5V
% 零待機功耗
% 可測量-55°C至+ 125°C的溫度, 華氏溫度等效值為-67°F至+ 257°F
% -10°C至+ 85°C的±0.5°C精度
% 溫度計解析度可在9到12位(bit位)之間編程
% 在750毫秒內(最大)將12位(bit位)溫度轉換為數字字(2Byte)
% 用戶定義的非易失性溫度警報設定
% 警報搜索命令可識別和尋址溫度超出編程限制的設備(溫度警報條件)
% 應用場景包括恒溫控制,工業系統,消費產品,溫度計或任何熱敏系統
7.2 下位機開發板上DS18B20原理圖
7.3 下位機實作讀取DS18B20傳感器溫度值
7.4 實作上位機與下位機通信的串口指令
上位機代碼
上位機向下位機發送"g\r\n"字串
void MainWindow::openSerialPort()
{
// 略:串口初始化,參看第6節
timer->start(TIMER_INTVAL); // 開啟定時器,定時發送獲取溫度指令
} else {
// 略
}
}
// 執行定時任務函式:發送獲取溫度指令
void MainWindow::sendTempCommand()
{
writeData("g\r\n");
}
下位機代碼
下位機接收到指令后進行決議,如果收到"g\r\n"指令則向上位機發送DS18B20的溫度值,格式為: "+25.2\r\n" 或者 "-25.2\r\n"
int main(void)
{
uint32_t i = 0;
int16_t tempValue;
uint8_t tempStr[8] = {0,0,0,0,0,0,0,0}; /*溫度字串*/
uint16_t len;
/* 初始化 */
FLASH_Init(); //FLASH芯片初始化
SYSTICK_Config(); //系統時鐘初始化
USART1_Config(9600); //USART1串口初始化
NVIC_Config(); //初始化中斷分組
DS18B20_Init(); //溫度傳感器初始化
while(1)
{
/* 方案1:周期性主動發送DS18B20溫度資料 */
// 方案2:收到獲取溫度指令后再發送溫度值
tempValue = DS18B20_ReadTemp();
GUI_DisplayTempData(tempValue);
// 檢測是否收到溫度獲取指令
if((USART2_RX_State & 0x80))
{
// 取得接收到的資料長度
USART2_RX_State = USART2_RX_State & 0x3F;
if( 'g' == USART2_RX_Buff[0]) // 收到獲取溫度指令:g\r\n
{
//將溫度發回串口
memset(tempStr, 0, sizeof(tempStr));
int16ToChar(tempValue, tempStr);
for(len=0; len < sizeof(tempStr); len++)
{
USART_SendData(USART2, tempStr[len]);
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) != SET); //等待發送完畢
}
}
USART2_RX_State = 0;
}
} // end while
}
/****************************************************************************
* Function Name : DS18B20_ReadTemp
* Description : 讀取溫度值.
* Input : None
* Output : None
* Return : temp:讀取到的溫度值,并保留兩位小數點(百倍),
****************************************************************************/
int16_t DS18B20_ReadTemp(void)
{
int16_t tempValue = 0;
uint16_t temp;
DS18B20_Reset();
DS18B20_WriteData(0xCC); //跳過ROM操作命令
DS18B20_WriteData(0x44); //溫度轉換命令
/* 如果不是連續讀的話,這里加個延時,DS18B20轉換溫度需要時間 */
// SYSTICK_Delay1ms(200);
DS18B20_Reset();
DS18B20_WriteData(0xCC); //跳過ROM操作命令
DS18B20_WriteData(0xBE); //發送讀取溫度命令
/* 讀取16位溫度值,先讀低位 */
temp = DS18B20_ReadData();
tempValue = DS18B20_ReadData();
tempValue <<= 8;
tempValue |= temp;
temp = tempValue;
/* 溫度處理,溫度保留兩位小數點 */
if(tempValue < 0)
{
temp = temp - 1;
temp = ~temp;
temp = (float)temp * 6.25 + 0.5;
return (-temp);
}
else
{
temp = (float)temp * 6.25+ 0.5;
return temp;
}
}
7.5 上位機溫度曲線顯示功能實作

void MainWindow::readData()
{
QByteArray data = serial->readAll();
QString str(data);
tempStr += str;
QStringList strList;
QRegExp rx("(\\+\\d+\\.\\d+)\\r\\n");
int pos = rx.indexIn(tempStr);
if( -1 < pos)
{
qDebug() << tempStr;
tempStr.clear();
strList.append(rx.cap(1));
}
else
{
return;
}
for(int i = 0; i < strList.size(); ++i)
{
QString item = strList.at(i);
if( item.length() < 5) continue;
float num = item.toFloat();
qint64 current_time_total_ms = QDateTime::currentMSecsSinceEpoch();
lineseries.append(current_time_total_ms + TIMER_INTVAL, num);
}
}
7.6 效果展示
圖7-6-1中保鮮膜包裹的即為DS18B20溫度傳感器(為測驗水溫,包裹保鮮膜保護傳感器),
上位機收到下位機的持續溫度值之后就可以繪制曲線了,圖7-6-2中的曲線是使用Qt的QtCharts::QChart類實作,
首先一小段平緩曲線是“室溫”,接下來將DS18B20放入溫水中,觀察曲線進入上升階段直至60.5度附近,然后將DS18B20從溫水中取出,曲線進入緩慢下降階段,向溫水中摻入一定量開水,再將DS18B20放入熱水中,觀察發現曲線陡然快速上升,達到80.8度附近將DS18B20從熱水中取出,最后放置在空氣中,靜待其降溫!
整個操作程序中完成溫度曲線如圖7-6-3所示,
注意:整個熱水溫度測量時長為10分鐘,觀察Gif圖片效果需要點耐心,
參考
[1] UART簡介及與COM口的區別
[2] 串口通信的具體用途是什么
[3] 串口通訊介紹
[4] 串口通信簡介
[5] DS18B20 Programmable Resolution 1-Wire? Digital Thermometer
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/277404.html
標籤:其他
