0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

內(nèi)存是怎么讀取數(shù)據(jù)的

h1654155149.6853 ? 來(lái)源:果果小師弟 ? 作者:智果芯 ? 2022-03-30 13:52 ? 次閱讀

摘要:你知道內(nèi)存是怎么讀取數(shù)據(jù)的嗎?知道數(shù)據(jù)是怎么一個(gè)一個(gè)字節(jié)發(fā)送的嗎?是低字節(jié)先發(fā)還是高字節(jié)先發(fā)?是bit0先發(fā)還是bit7先發(fā)?是從低地址開(kāi)始讀還是從高地址開(kāi)始讀?看完本篇你應(yīng)該就明白了~

內(nèi)存的讀寫(xiě)永遠(yuǎn)從低地址開(kāi)始讀/寫(xiě),從低到高!從低到高!從低到高!重要的話說(shuō)三遍

大端模式和小端模式

大端模式和小端是實(shí)際的字節(jié)順序和存儲(chǔ)的地址順序?qū)?yīng)關(guān)系的兩種模式。

大端模式:高位字節(jié)存放在低地址中,低位字節(jié)存放在高地址中。最直觀的字節(jié)序。

小端模式:高位字節(jié)存放在高地址中,低位字節(jié)存放在低地址中。最符合人的思維的字節(jié)序,x86、ARM都這么搞(STM32就是小端模式存儲(chǔ))。

用圖表示更加容易理解。以u(píng)nsigned int value = 0x12345678為例,分別按照大端模式和小端模式存放在芯片中。

內(nèi)存地址 0x00000001 0x00000002 0x00000003 0x00000004
大端模式 0x12 0x34 0x56 0x78
小端模式 0x78 0x56 0x34 0x12

再換一種圖示:同樣以u(píng)nsigned int value = 0x12345678為例,分別看看在兩種字節(jié)序下其存儲(chǔ)情況,我們可以用unsigned char buf[4]來(lái)表示value。

6bef331a-afd2-11ec-aa7f-dac502259ad0.png百度百科

不管是大端還是小端模式,我們?cè)谧x取和存儲(chǔ)數(shù)據(jù)的時(shí)候一定都是從內(nèi)存的低地址依次向高地址讀取或?qū)懭搿A硗庾⒁?,x86平臺(tái)是小端的,ARM平臺(tái)是小端的,而PowerPC平臺(tái)是大端的。

字節(jié)高低位

一般左邊為高位,右邊為低位(這個(gè)高低來(lái)自于人類(lèi)的閱讀習(xí)慣,數(shù)字從左向右,表示由大到小)

一個(gè)16位(雙字節(jié))的數(shù)據(jù),比如0xFF12,那么高位字節(jié)就是0xFF,低位是0x12。如果是32位的數(shù)據(jù),比如0x12345678。高位字(不是字節(jié))是0x1234,低位字是0x5678。

右邊是低位位,左邊是高位(人的閱讀習(xí)慣)

LSB和MSB

最高有效位(most mignificant bit,msb)指的是一個(gè)n位二進(jìn)制數(shù)字中的n-1位,具有最高的權(quán)值2^(n-1)。有時(shí)也指Most Significant Byte(MSB),指多字節(jié)序列中具有最大權(quán)重的字節(jié)。

同理,最低有效位(least significant bit,lsb)和的是一個(gè)n位二進(jìn)制數(shù)字中的0位,具有最低的權(quán)值2^0。有時(shí)也指Least Significant Byte(LSB),指多字節(jié)序列中具有最小權(quán)重的字節(jié)。

所以0x12345678的最高有效字節(jié)就是0x12,最低有效字節(jié)就是0x78,這樣明白了吧!

舉個(gè)栗子

當(dāng)選擇模數(shù)轉(zhuǎn)換器(ADC)時(shí),最低有效位(LSB)這一參數(shù)的含義是什么?

對(duì)于一個(gè)12位串行轉(zhuǎn)換器,它會(huì)輸出由1或0組成的12位數(shù)串。通常,轉(zhuǎn)換器首先送出的是最高有效位(MSB)(即LSB + 11)。有些轉(zhuǎn)換器也會(huì)先送出LSB。我們假設(shè)先送出的是MSB,然后依次送出MSB-1 (即 LSB + 10)和MSB -2(即LSB + 9)并依次類(lèi)推。轉(zhuǎn)換器最終送出MSB -11(即LSB)作為位串的末位。

LSB這一術(shù)語(yǔ)有著特定的含義,它表示的是數(shù)字流中的最后一位,也表示組成滿量程輸入范圍的最小單位。對(duì)于12位轉(zhuǎn)換器來(lái)說(shuō),LSB的值相當(dāng)于模擬信號(hào)滿量程輸入范圍除以2^12 或 4096的商。如果用真實(shí)的數(shù)字來(lái)表示的話,對(duì)于滿量程輸入范圍為4.096V的情況,一個(gè)12位轉(zhuǎn)換器對(duì)應(yīng)的LSB大小為1mV。但是,將LSB定義為4096個(gè)可能編碼中的一個(gè)編碼對(duì)于我們的理解是有好處的。

6c02ef72-afd2-11ec-aa7f-dac502259ad0.png截取自某12位ADC芯片數(shù)據(jù)手冊(cè)

高位先行msb 、低位先行l(wèi)sb

高位先行即在傳輸一個(gè)字節(jié)的時(shí)候先傳輸高位msb;低位先行即在傳輸一個(gè)字節(jié)的時(shí)候先傳輸?shù)臀籰sb。高位先行和低位先行是針對(duì)串行數(shù)據(jù)傳輸方式來(lái)說(shuō)的。常見(jiàn)的串行傳輸方式有串口(UART)、I2C、SPI等。以串口傳輸方式為例,標(biāo)準(zhǔn)的串口傳輸方式是低位先行,芯片在通過(guò)TX引腳發(fā)送數(shù)據(jù)時(shí),依次發(fā)送位0、位1……位7。

串口傳輸是低位先行

UART在數(shù)據(jù)傳輸時(shí),協(xié)議規(guī)定了數(shù)據(jù)傳輸必須是低位先行,看下面的時(shí)序圖你就知道了~

6c21bf74-afd2-11ec-aa7f-dac502259ad0.png截圖自STM32F407中文參考手冊(cè)

IIC傳輸是高位先行

IIC的數(shù)據(jù)和地址均以8位字節(jié)傳輸,MSB 在前。從圖中可以清楚地看到:

6c3eb6ba-afd2-11ec-aa7f-dac502259ad0.png截圖自STM32F407中文參考手冊(cè)IIC部分

這一點(diǎn)也反映在代碼中,我們隨便找一個(gè)IIC的讀字節(jié)和寫(xiě)字節(jié)的函數(shù)看看:

voidi2c_SendByte(uint8_t_ucByte)
{
uint8_ti;
/*先發(fā)送字節(jié)的高位bit7*/
for(i=0;i

從第7行代碼中可以看到,在發(fā)送一個(gè)字節(jié)時(shí),首先將要發(fā)送的字節(jié)與0x80進(jìn)行與運(yùn)算,取出最高位,然后循環(huán)左移8次就可以將一個(gè)字節(jié)數(shù)據(jù)發(fā)送出去了。你有沒(méi)有想過(guò)為什么這里我們不把要發(fā)送的字節(jié)與0x01進(jìn)行與運(yùn)算,取出最低位,然后循環(huán)右移8次也可以將一個(gè)字節(jié)數(shù)據(jù)發(fā)送出去呢?

答:因?yàn)槲覀冋f(shuō)了I2C在數(shù)據(jù)傳輸時(shí),協(xié)議規(guī)定了數(shù)據(jù)傳輸必須是高位先行,所以你要發(fā)送一個(gè)字節(jié)的數(shù)據(jù)肯定必須先取出最高位,然后循環(huán)左移將數(shù)據(jù)發(fā)出,如果你與上0x01,就是低位先行,雖然你也將一個(gè)字節(jié)發(fā)出去了,但是你發(fā)的是歪門(mén)邪道的數(shù)據(jù),人家單片機(jī)也不認(rèn)識(shí),對(duì)吧?你品,你細(xì)品

同樣在接收一個(gè)字節(jié)時(shí),接收到的第1位認(rèn)為是最高位,接收一個(gè)字節(jié)代碼如下:

uint8_ti2c_ReadByte(void)
{
uint8_ti;
uint8_tvalue;
/*讀到第1個(gè)bit為數(shù)據(jù)的bit7*/
value=0;
for(i=0;i

所有使用I2C的設(shè)備必須遵循I2C協(xié)議,必須都是高位先行的,這樣才能實(shí)現(xiàn)通用性。怎么樣?是不是又get到了一個(gè)小技巧~

字節(jié)序、比特序

字節(jié)序就是串行發(fā)送多字節(jié)時(shí)發(fā)送的順序,比如value=0x12345678,按字節(jié)發(fā)送是0x12、0x34、0x56、0x78順序還是0x78、0x56、0x34、0x12順序。

同理,比特序在bit層面進(jìn)行排序,如果一個(gè)字節(jié),指先發(fā)bit0還是bit7, 如果是一個(gè)Word型,先發(fā)bit31還是先發(fā)bit0。串口是lsb優(yōu)先,I2C是msb優(yōu)先,這里的msb、lsb指的是比特序,二進(jìn)制位的位置。

驗(yàn)證MCU平臺(tái)存儲(chǔ)方式?

這里以STM32開(kāi)發(fā)單片機(jī)的keil平臺(tái)為例,以下代碼如果打印0x04就是小端存儲(chǔ),如果0x01則是大端存儲(chǔ)。

因?yàn)?x04是低字節(jié),讀取數(shù)據(jù)是從低地址開(kāi)始讀,打印的是data的低地址,所以如果打印出的是0x04就表明低地址存儲(chǔ)低字節(jié),就為小端存儲(chǔ)。明白了嗎?

6c674832-afd2-11ec-aa7f-dac502259ad0.png

#include"sys.h"
#include"delay.h"
#include"usart.h"
#include"led.h"
#include"key.h"
#include"lcd.h"
#include"SEGGER_RTT.h"
#include"math.h"

intmain(void)
{
HAL_Init();//初始化HAL庫(kù)
Stm32_Clock_Init(8,336,2,7);//設(shè)置時(shí)鐘,168Mhz
delay_init(168);//初始化延時(shí)函數(shù)
while(1)
{
uint32_tdata=0x01020304;
char*p=(char*)&data;
printf("0x0%x
",*p);//看輸出的是0x01還是0x04
delay_ms(1000);
}
}

編譯、鏈接、下載,通過(guò)RTT查看試驗(yàn)結(jié)果:

6c7cbbd6-afd2-11ec-aa7f-dac502259ad0.pngJLink的RTT查看器

可以看出STM32是小端存儲(chǔ)。

總結(jié):內(nèi)存的讀寫(xiě)永遠(yuǎn)從低地址開(kāi)始讀/寫(xiě)。大小端存儲(chǔ)指字節(jié)在內(nèi)存存儲(chǔ)方式,X86、ARM平臺(tái)都是小端存儲(chǔ)(低-低),MSB/LSB只發(fā)送字節(jié)序或者比特序,串口是比特序LSB,IIC是比特序MSB。也有人將MSB、big-endian、大端發(fā)送都混為一談,這時(shí)候一般指字節(jié)序上MSB。

原文標(biāo)題:干貨|一文帶你搞懂內(nèi)存中數(shù)據(jù)的讀寫(xiě)方式

文章出處:【微信公眾號(hào):電子工程世界】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

審核編輯:彭菁
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    6808

    瀏覽量

    88743
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2966

    瀏覽量

    73812
  • STM32
    +關(guān)注

    關(guān)注

    2264

    文章

    10854

    瀏覽量

    354291
  • 存儲(chǔ)數(shù)據(jù)

    關(guān)注

    0

    文章

    85

    瀏覽量

    14082

原文標(biāo)題:干貨|一文帶你搞懂內(nèi)存中數(shù)據(jù)的讀寫(xiě)方式

文章出處:【微信號(hào):電子工程世界,微信公眾號(hào):電子工程世界】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    問(wèn)題:讀取數(shù)據(jù)時(shí)報(bào)錯(cuò)內(nèi)存不足

    大家好,最近在處理數(shù)據(jù)的時(shí)候遇到這樣一個(gè)問(wèn)題,使用讀取電子表格來(lái)讀一個(gè)300M左右的TXT數(shù)據(jù)文件,運(yùn)行時(shí)間很長(zhǎng)并且報(bào)錯(cuò)內(nèi)存不足,有什么辦法能解決這個(gè)問(wèn)題嗎?謝謝各位了
    發(fā)表于 01-18 22:55

    TDMS文件,讀取顯示內(nèi)存已滿

    讀取存儲(chǔ)的TDMS波形數(shù)據(jù),只有采集1分鐘的數(shù)據(jù),大概27MB的大小,為什么讀取不出來(lái)呢?顯示沒(méi)有足夠的內(nèi)存?TDMS不是存儲(chǔ)海量
    發(fā)表于 09-23 11:33

    一次讀取數(shù)據(jù)占用內(nèi)存很大

    本帖最后由 elecfans跑堂 于 2015-8-31 10:50 編輯 在編寫(xiě)一個(gè)讀取wav文件的程序,發(fā)現(xiàn)一次讀取40M以上的文件,消耗內(nèi)存1G左右,太嚇人了,請(qǐng)高手指點(diǎn)啊http
    發(fā)表于 08-31 09:40

    Linux學(xué)習(xí)記錄——寄存器與內(nèi)存

    之前搞不懂寄存器與內(nèi)存的區(qū)別 使用匯編指令的時(shí)候,Mov, ldr, str 搞不清三者間的區(qū)別:Mov 是用于寄存器間的數(shù)據(jù)傳送ldr 是從內(nèi)存讀取
    發(fā)表于 01-12 10:43

    利用SRIO接口從FPGA向6678的共享內(nèi)存發(fā)送數(shù)據(jù),請(qǐng)問(wèn)相比于單核從共享內(nèi)存讀取數(shù)據(jù)會(huì)慢多少?

    段發(fā)送數(shù)據(jù),第一段數(shù)據(jù)由核0處理,第二段數(shù)據(jù)由核1處理,第三段……第八段數(shù)據(jù)由核7處理。想問(wèn)一下,這種機(jī)制相比于單核從共享內(nèi)存
    發(fā)表于 06-25 01:31

    狀態(tài)機(jī)運(yùn)行沒(méi)有約束是為什么?

    我一直在研究一個(gè)從DDR3內(nèi)存讀取數(shù)據(jù)并通過(guò)以太網(wǎng)發(fā)送數(shù)據(jù)用于PC Matlab數(shù)據(jù)捕獲的系統(tǒng)。我有兩臺(tái)狀態(tài)機(jī)。 1個(gè)狀態(tài)機(jī)只有3個(gè)狀態(tài)。寫(xiě)
    發(fā)表于 06-14 17:46

    嵌入式C語(yǔ)言一些關(guān)鍵字的相關(guān)資料推薦

    要求使用 volatile 聲明變量值的時(shí)候,系統(tǒng)總是重新從它所在的內(nèi)存讀取數(shù)據(jù),即使它前面的指令剛剛從該處讀取過(guò)數(shù)據(jù)。遇到這個(gè)關(guān)鍵字聲明的
    發(fā)表于 12-15 08:36

    DMA_讀取GPIO電平到內(nèi)存

    DMA_讀取GPIO電平到內(nèi)存,單片機(jī)程序
    發(fā)表于 01-12 18:19 ?10次下載

    java之volatile并發(fā)

    模型的相關(guān)概念 大家都知道,計(jì)算機(jī)在執(zhí)行程序時(shí),每條指令都是在CPU中執(zhí)行的,而執(zhí)行指令過(guò)程中,勢(shì)必涉及到數(shù)據(jù)讀取和寫(xiě)入。由于程序運(yùn)行過(guò)程中的臨時(shí)數(shù)據(jù)是存放在主存(物理內(nèi)存)當(dāng)中的,
    發(fā)表于 09-27 10:20 ?6次下載
    java之volatile并發(fā)

    windows應(yīng)用程序讀取進(jìn)程的內(nèi)存工具免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是windows應(yīng)用程序讀取進(jìn)程的內(nèi)存工具免費(fèi)下載。
    發(fā)表于 05-27 08:00 ?1次下載

    CPU是如何調(diào)度任務(wù)的?

    ②. 1 號(hào)核心讀取變量 A,由于 CPU 從內(nèi)存讀取數(shù)據(jù)到 Cache 的單位是 Cache Line,也正好變量 A 和 變量 B 的數(shù)據(jù)
    的頭像 發(fā)表于 12-11 16:44 ?3140次閱讀
    CPU是如何調(diào)度任務(wù)的?

    干貨|一文帶你搞懂內(nèi)存數(shù)據(jù)的讀寫(xiě)方式

    摘要:你知道內(nèi)存是怎么讀取數(shù)據(jù)的嗎?知道數(shù)據(jù)是怎么一個(gè)一個(gè)字節(jié)發(fā)送的嗎?是低字節(jié)先發(fā)還是高字節(jié)先發(fā)?是bit0先發(fā)還是bit7先發(fā)?是...
    發(fā)表于 01-25 17:21 ?0次下載
    干貨|一文帶你搞懂<b class='flag-5'>內(nèi)存</b>中<b class='flag-5'>數(shù)據(jù)</b>的讀寫(xiě)方式

    關(guān)于Vivado Non-project,我們應(yīng)知道的一些問(wèn)題

    ,同時(shí)也便于工程管理。Non-Project模式編譯時(shí)間會(huì)比Project模式短,因?yàn)樗?b class='flag-5'>數(shù)據(jù)存儲(chǔ)在內(nèi)存,直接內(nèi)存讀取數(shù)據(jù)比硬盤(pán)
    的頭像 發(fā)表于 12-15 13:51 ?1950次閱讀

    PCI Express橋:指南上游內(nèi)存讀取性能優(yōu)化

    電子發(fā)燒友網(wǎng)站提供《PCI Express橋:指南上游內(nèi)存讀取性能優(yōu)化.pdf》資料免費(fèi)下載
    發(fā)表于 07-24 16:21 ?0次下載
    PCI Express橋:指南上游<b class='flag-5'>內(nèi)存</b><b class='flag-5'>讀取</b>性能優(yōu)化

    蘇州旗芯微半導(dǎo)體專(zhuān)利:內(nèi)存數(shù)據(jù)讀取方法、系統(tǒng)及計(jì)算機(jī)設(shè)備

    此項(xiàng)申請(qǐng)主要涉及內(nèi)存數(shù)據(jù)讀取方法、系統(tǒng)及計(jì)算機(jī)設(shè)備。在其中一個(gè)實(shí)施案例里,內(nèi)存能夠在接到主機(jī)的讀取指令后,從
    的頭像 發(fā)表于 05-24 09:48 ?336次閱讀
    蘇州旗芯微半導(dǎo)體專(zhuān)利:<b class='flag-5'>內(nèi)存</b><b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>讀取</b>方法、系統(tǒng)及計(jì)算機(jī)設(shè)備