樹莓派基礎(chǔ)實(shí)驗(yàn)30:BMP180氣壓傳感器實(shí)驗(yàn)

一蛇券、介紹

?? BMP180氣壓計(jì)是新型數(shù)字氣壓傳感器缀壤,具有非常高的性能,可用于高級(jí)移動(dòng)設(shè)備纠亚,如智能手機(jī)塘慕,平板電腦和運(yùn)動(dòng)設(shè)備。它兼容BMP085傳感器菜枷,但是在該基礎(chǔ)上擁有許多改進(jìn)苍糠,如更小的尺寸和更多的數(shù)字接口叁丧。

??BMP180不僅可以實(shí)時(shí)的測(cè)量大氣壓力啤誊,還能測(cè)量實(shí)時(shí)溫度岳瞭。同時(shí)它還具有IIC總線的接口,便于單片機(jī)進(jìn)行訪問蚊锹。另外它的使用也很方便瞳筏,不需要太多的操作就可讀取到氣壓及測(cè)量數(shù)據(jù)。

??其它I2C總線實(shí)驗(yàn)可以查看前面的PCF8591相關(guān)實(shí)驗(yàn)牡昆,如:
??樹莓派基礎(chǔ)實(shí)驗(yàn)12:PCF8591模數(shù)轉(zhuǎn)換器實(shí)驗(yàn)

二姚炕、組件

★Raspberry Pi 3主板*1

★樹莓派電源*1

★40P軟排線*1

★BMP180氣壓傳感器模塊*1

★面包板*1

★跳線若干

三、實(shí)驗(yàn)原理

BMP180氣壓傳感器
BMP180大氣壓檢測(cè)傳感器模塊原理圖

測(cè)量溫度和壓力

?? UP =壓力數(shù)據(jù)(16到19位) UT =溫度數(shù)據(jù)(16位)

??開始測(cè)量溫度值UT和壓力值UP的時(shí)序圖如下所示丢烘。在啟動(dòng)后柱宦,主機(jī)發(fā)送器件地址寫入,寄存器地址和控制寄存器數(shù)據(jù)播瞳。當(dāng)接收到數(shù)據(jù)時(shí)掸刊,BMP180每8個(gè)數(shù)據(jù)位發(fā)送一個(gè)確認(rèn)(ACKS)。主機(jī)在最后一次ACKS后發(fā)送停止條件赢乓。

??為了讀出溫度數(shù)據(jù)字UT(16位)忧侧,壓力數(shù)據(jù)字UP(16到19位)和E2PROM數(shù)據(jù)如下進(jìn)行:
??在啟動(dòng)后,主機(jī)發(fā)送模塊地址寫入命令和寄存器地址牌芋。寄存器地址選擇讀取寄存器:E2PROM數(shù)據(jù)寄存器0xAA至0xBF溫度或壓力值UT或UP 0xF6(MSB)蚓炬,0xF7(LSB),可選0xF8(XLSB)然后躺屁,主設(shè)備發(fā)送重啟條件肯夏,然后讀取模塊地址,BMP180(ACKS)將對(duì)其進(jìn)行確認(rèn)犀暑。BMP180首先發(fā)送8個(gè)MSB熄捍,由主設(shè)備(ACKM)確認(rèn),然后是8個(gè)LSB母怜。主機(jī)發(fā)送“不確認(rèn)”(NACKM)余耽,最后發(fā)送停止條件。時(shí)序?yàn)椋?/p>

??下圖顯示了壓力和溫度測(cè)量的詳細(xì)算法:


壓力和溫度的算法

四苹熏、實(shí)驗(yàn)步驟

??第1步:連接電路碟贾。

樹莓派 T型轉(zhuǎn)接板 BMP180氣壓傳感器
SCL SCL SCL
SDA SDA SDA
3.3V 3.3V VCC
GND GND GND
BMP180氣壓傳感器實(shí)驗(yàn)電路圖
BMP180氣壓傳感器實(shí)驗(yàn)實(shí)物接線圖

??第2步:PCF8591模塊采用的是I2C(IIC)總線進(jìn)行通信的,但是在樹莓派的鏡像中默認(rèn)是關(guān)閉的轨域,在使用該傳感器的時(shí)候袱耽,我們必須首先允許IIC總線通信。

打開I2C總線通信

??第3步:查詢LCD1602的地址干发。得出地址為0x77朱巨。

pi@raspberrypi:~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77                         

??第4步:編寫驅(qū)動(dòng)程序。這里需要下載安裝庫函數(shù)枉长,核心是BMP085.py文件冀续,后面編寫一個(gè)python控制程序時(shí)引入這個(gè)庫文件琼讽,調(diào)用這個(gè)文件中的函數(shù)實(shí)現(xiàn)更復(fù)雜的功能。
??該庫函數(shù)來自:
https://github.com/adafruit/Adafruit_Python_BMP/

Adafruit_Python_BMP

??這是由Adafruit Industries公司制作的Python庫洪唐,在該地址可以將整個(gè)Adafruit_Python_BMP文件夾下載使用钻蹬。該公司成立于2005年,創(chuàng)始人是來自麻省理工學(xué)院的女工程師Limor凭需,目標(biāo)是打造一個(gè)學(xué)習(xí)電子產(chǎn)品相關(guān)知識(shí)和為各個(gè)年齡階段與技能水平不等的客戶設(shè)計(jì)產(chǎn)品的場(chǎng)所问欠。總部位于美國(guó)紐約的中心區(qū)粒蜈。


Limor

??第5步:安裝I2C的smbus及一些實(shí)用程序顺献。

pi@raspberrypi:~ $ sudo apt-get install python-smbus i2c-tools
pi@raspberrypi:~ $ sudo apt-get install build-essential python-dev 

??第6步:將下載的整個(gè)Adafruit_Python_BMP文件夾復(fù)制到Pi目錄下,進(jìn)入Adafruit_Python_BMP目錄枯怖,安裝BMP的操作庫:

pi@raspberrypi:~ $ cd Adafruit_Python_BMP/
pi@raspberrypi:~/Adafruit_Python_BMP $ sudo python setup.py install

??該文件夾下有一些參考資料滚澜,BMP085.py文件就在第二個(gè)文件夾Adafruit_BMP里面:


Adafruit_Python_BMP目錄

下面是核心文件BMP085.py的代碼,供深入研究的同學(xué)參考:

# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import logging
import time


# BMP085 default address.
BMP085_I2CADDR           = 0x77

# Operating Modes
BMP085_ULTRALOWPOWER     = 0
BMP085_STANDARD          = 1
BMP085_HIGHRES           = 2
BMP085_ULTRAHIGHRES      = 3

# BMP085 Registers
BMP085_CAL_AC1           = 0xAA  # R   Calibration data (16 bits)
BMP085_CAL_AC2           = 0xAC  # R   Calibration data (16 bits)
BMP085_CAL_AC3           = 0xAE  # R   Calibration data (16 bits)
BMP085_CAL_AC4           = 0xB0  # R   Calibration data (16 bits)
BMP085_CAL_AC5           = 0xB2  # R   Calibration data (16 bits)
BMP085_CAL_AC6           = 0xB4  # R   Calibration data (16 bits)
BMP085_CAL_B1            = 0xB6  # R   Calibration data (16 bits)
BMP085_CAL_B2            = 0xB8  # R   Calibration data (16 bits)
BMP085_CAL_MB            = 0xBA  # R   Calibration data (16 bits)
BMP085_CAL_MC            = 0xBC  # R   Calibration data (16 bits)
BMP085_CAL_MD            = 0xBE  # R   Calibration data (16 bits)
BMP085_CONTROL           = 0xF4
BMP085_TEMPDATA          = 0xF6
BMP085_PRESSUREDATA      = 0xF6

# Commands
BMP085_READTEMPCMD       = 0x2E
BMP085_READPRESSURECMD   = 0x34


class BMP085(object):
    def __init__(self, mode=BMP085_STANDARD, address=BMP085_I2CADDR, i2c=None, **kwargs):
        self._logger = logging.getLogger('Adafruit_BMP.BMP085')
        # Check that mode is valid.
        if mode not in [BMP085_ULTRALOWPOWER, BMP085_STANDARD, BMP085_HIGHRES, BMP085_ULTRAHIGHRES]:
            raise ValueError('Unexpected mode value {0}.  Set mode to one of BMP085_ULTRALOWPOWER, BMP085_STANDARD, BMP085_HIGHRES, or BMP085_ULTRAHIGHRES'.format(mode))
        self._mode = mode
        # Create I2C device.
        if i2c is None:
            import Adafruit_GPIO.I2C as I2C
            i2c = I2C
        self._device = i2c.get_i2c_device(address, **kwargs)
        # Load calibration values.
        self._load_calibration()

    def _load_calibration(self):
        self.cal_AC1 = self._device.readS16BE(BMP085_CAL_AC1)   # INT16
        self.cal_AC2 = self._device.readS16BE(BMP085_CAL_AC2)   # INT16
        self.cal_AC3 = self._device.readS16BE(BMP085_CAL_AC3)   # INT16
        self.cal_AC4 = self._device.readU16BE(BMP085_CAL_AC4)   # UINT16
        self.cal_AC5 = self._device.readU16BE(BMP085_CAL_AC5)   # UINT16
        self.cal_AC6 = self._device.readU16BE(BMP085_CAL_AC6)   # UINT16
        self.cal_B1 = self._device.readS16BE(BMP085_CAL_B1)     # INT16
        self.cal_B2 = self._device.readS16BE(BMP085_CAL_B2)     # INT16
        self.cal_MB = self._device.readS16BE(BMP085_CAL_MB)     # INT16
        self.cal_MC = self._device.readS16BE(BMP085_CAL_MC)     # INT16
        self.cal_MD = self._device.readS16BE(BMP085_CAL_MD)     # INT16
        self._logger.debug('AC1 = {0:6d}'.format(self.cal_AC1))
        self._logger.debug('AC2 = {0:6d}'.format(self.cal_AC2))
        self._logger.debug('AC3 = {0:6d}'.format(self.cal_AC3))
        self._logger.debug('AC4 = {0:6d}'.format(self.cal_AC4))
        self._logger.debug('AC5 = {0:6d}'.format(self.cal_AC5))
        self._logger.debug('AC6 = {0:6d}'.format(self.cal_AC6))
        self._logger.debug('B1 = {0:6d}'.format(self.cal_B1))
        self._logger.debug('B2 = {0:6d}'.format(self.cal_B2))
        self._logger.debug('MB = {0:6d}'.format(self.cal_MB))
        self._logger.debug('MC = {0:6d}'.format(self.cal_MC))
        self._logger.debug('MD = {0:6d}'.format(self.cal_MD))

    def _load_datasheet_calibration(self):
        # Set calibration from values in the datasheet example.  Useful for debugging the
        # temp and pressure calculation accuracy.
        self.cal_AC1 = 408
        self.cal_AC2 = -72
        self.cal_AC3 = -14383
        self.cal_AC4 = 32741
        self.cal_AC5 = 32757
        self.cal_AC6 = 23153
        self.cal_B1 = 6190
        self.cal_B2 = 4
        self.cal_MB = -32767
        self.cal_MC = -8711
        self.cal_MD = 2868

    def read_raw_temp(self):
        """Reads the raw (uncompensated) temperature from the sensor."""
        self._device.write8(BMP085_CONTROL, BMP085_READTEMPCMD)
        time.sleep(0.005)  # Wait 5ms
        raw = self._device.readU16BE(BMP085_TEMPDATA)
        self._logger.debug('Raw temp 0x{0:X} ({1})'.format(raw & 0xFFFF, raw))
        return raw

    def read_raw_pressure(self):
        """Reads the raw (uncompensated) pressure level from the sensor."""
        self._device.write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (self._mode << 6))
        if self._mode == BMP085_ULTRALOWPOWER:
            time.sleep(0.005)
        elif self._mode == BMP085_HIGHRES:
            time.sleep(0.014)
        elif self._mode == BMP085_ULTRAHIGHRES:
            time.sleep(0.026)
        else:
            time.sleep(0.008)
        msb = self._device.readU8(BMP085_PRESSUREDATA)
        lsb = self._device.readU8(BMP085_PRESSUREDATA+1)
        xlsb = self._device.readU8(BMP085_PRESSUREDATA+2)
        raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self._mode)
        self._logger.debug('Raw pressure 0x{0:04X} ({1})'.format(raw & 0xFFFF, raw))
        return raw

    def read_temperature(self):
        """Gets the compensated temperature in degrees celsius."""
        UT = self.read_raw_temp()
        # Datasheet value for debugging:
        #UT = 27898
        # Calculations below are taken straight from section 3.5 of the datasheet.
        X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
        X2 = (self.cal_MC << 11) / (X1 + self.cal_MD)
        B5 = X1 + X2
        temp = ((B5 + 8) >> 4) / 10.0
        self._logger.debug('Calibrated temperature {0} C'.format(temp))
        return temp

    def read_pressure(self):
        """Gets the compensated pressure in Pascals."""
        UT = self.read_raw_temp()
        UP = self.read_raw_pressure()
        # Datasheet values for debugging:
        #UT = 27898
        #UP = 23843
        # Calculations below are taken straight from section 3.5 of the datasheet.
        # Calculate true temperature coefficient B5.
        X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
        X2 = (self.cal_MC << 11) / (X1 + self.cal_MD)
        B5 = X1 + X2
        self._logger.debug('B5 = {0}'.format(B5))
        # Pressure Calculations
        B6 = B5 - 4000
        self._logger.debug('B6 = {0}'.format(B6))
        X1 = (self.cal_B2 * (B6 * B6) >> 12) >> 11
        X2 = (self.cal_AC2 * B6) >> 11
        X3 = X1 + X2
        B3 = (((self.cal_AC1 * 4 + X3) << self._mode) + 2) / 4
        self._logger.debug('B3 = {0}'.format(B3))
        X1 = (self.cal_AC3 * B6) >> 13
        X2 = (self.cal_B1 * ((B6 * B6) >> 12)) >> 16
        X3 = ((X1 + X2) + 2) >> 2
        B4 = (self.cal_AC4 * (X3 + 32768)) >> 15
        self._logger.debug('B4 = {0}'.format(B4))
        B7 = (UP - B3) * (50000 >> self._mode)
        self._logger.debug('B7 = {0}'.format(B7))
        if B7 < 0x80000000:
            p = (B7 * 2) / B4
        else:
            p = (B7 / B4) * 2
        X1 = (p >> 8) * (p >> 8)
        X1 = (X1 * 3038) >> 16
        X2 = (-7357 * p) >> 16
        p = p + ((X1 + X2 + 3791) >> 4)
        self._logger.debug('Pressure {0} Pa'.format(p))
        return p

    def read_altitude(self, sealevel_pa=101325.0):
        """Calculates the altitude in meters."""
        # Calculation taken straight from section 3.6 of the datasheet.
        pressure = float(self.read_pressure())
        altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0/5.255)))
        self._logger.debug('Altitude {0} m'.format(altitude))
        return altitude

    def read_sealevel_pressure(self, altitude_m=0.0):
        """Calculates the pressure at sealevel when given a known altitude in
        meters. Returns a value in Pascals."""
        pressure = float(self.read_pressure())
        p0 = pressure / pow(1.0 - altitude_m/44330.0, 5.255)
        self._logger.debug('Sealevel pressure {0} Pa'.format(p0))
        return p0

            

??第5步:編寫控制程序嫁怀。每隔一秒打印一次氣壓和溫度數(shù)據(jù)设捐,由于我的所在地為高海拔的拉薩,所以氣壓數(shù)據(jù)低一些塘淑。

打印顯示氣壓和溫度

實(shí)際控制程序比較簡(jiǎn)單了萝招,如下:

#!/usr/bin/env python
#---------------------------------------------------------
#
#       This is a program for Barometer Pressure Sensor
#   Module. It could measure the pressure and temperature.
#
#       This program depend on BMP085.py writted by 
#   Adafruit. 
#
#      Barometer Module            Pi
#           VCC ----------------- 3.3V
#           GND ------------------ GND
#           SCL ----------------- SCL1
#           SDA ----------------- SDA1
#
#---------------------------------------------------------
import Adafruit_BMP.BMP085 as BMP085
import RPi.GPIO as GPIO
import time

def setup():
    print '\n Barometer begins...'

def loop():
    while True:
        sensor = BMP085.BMP085()
        temp = sensor.read_temperature()    # Read temperature to veriable temp
        pressure = sensor.read_pressure()   # Read pressure to veriable pressure

        print ''
        print '      Temperature = {0:0.2f} C'.format(temp)     # Print temperature保留小數(shù)點(diǎn)后兩位
        print '      Pressure = {0:0.2f} Pa'.format(pressure)   # Print pressure
        #字符串中大括號(hào)和其中的字符會(huì)被替換成傳入 str.format() 的參數(shù)。
        #字段名后允許可選的 ':' 和格式指令存捺。{0:0.2f}保留小數(shù)點(diǎn)后兩位
        time.sleep(1)           
        print ''

def destory():
    GPIO.cleanup()              # Release resource

if __name__ == '__main__':      # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destory()

其中使用的Python format 格式化函數(shù)詳情參見:
https://www.runoob.com/python/att-string-format.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末槐沼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子捌治,更是在濱河造成了極大的恐慌岗钩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,496評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肖油,死亡現(xiàn)場(chǎng)離奇詭異兼吓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)森枪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門视搏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人县袱,你說我怎么就攤上這事浑娜。” “怎么了式散?”我有些...
    開封第一講書人閱讀 157,091評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵筋遭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)漓滔,這世上最難降的妖魔是什么编饺? 我笑而不...
    開封第一講書人閱讀 56,458評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮次和,結(jié)果婚禮上反肋,老公的妹妹穿的比我還像新娘那伐。我一直安慰自己踏施,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評(píng)論 6 385
  • 文/花漫 我一把揭開白布罕邀。 她就那樣靜靜地躺著畅形,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诉探。 梳的紋絲不亂的頭發(fā)上日熬,一...
    開封第一講書人閱讀 49,802評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音肾胯,去河邊找鬼竖席。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敬肚,可吹牛的內(nèi)容都是我干的毕荐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,945評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼艳馒,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼憎亚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弄慰,我...
    開封第一講書人閱讀 37,709評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤第美,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后陆爽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體什往,經(jīng)...
    沈念sama閱讀 44,158評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評(píng)論 2 327
  • 正文 我和宋清朗相戀三年慌闭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恶守。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,637評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贡必,死狀恐怖兔港,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仔拟,我是刑警寧澤衫樊,帶...
    沈念sama閱讀 34,300評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響科侈,放射性物質(zhì)發(fā)生泄漏载佳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評(píng)論 3 313
  • 文/蒙蒙 一臀栈、第九天 我趴在偏房一處隱蔽的房頂上張望蔫慧。 院中可真熱鬧,春花似錦权薯、人聲如沸姑躲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黍析。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涛漂。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔼两,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,344評(píng)論 2 360
  • 正文 我出身青樓逞度,卻偏偏與公主長(zhǎng)得像额划,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子第晰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評(píng)論 2 348