當前位置:首頁 » 編程語言 » C語言CAN通信
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

C語言CAN通信

發布時間: 2022-12-28 22:20:07

A. CAN通信,C語言

使用一個flag
開始為0,當計數一次後變為一。
在計數時先判斷flag是否為0,若是則計數,若否則跳過

B. 哭求~~can匯流排的C語言程序例子

1 去買本北京航空航天大學出的書,好好看看。
2 或者自己用網路搜索。

這個問題估計沒人給你答案。要有也是網上搜的,還不如自己去搜。
網路輸入:can匯流排程序
會有很多結果,大把大把。
比如:
http://hi..com/wogoyixikexie/blog/item/4befa4166b94134f20a4e9b5.html
http://blog.21ic.com/user1/4416/archives/2007/41628.html

都是用c51寫的,也不難,小可也會。
做了一回黨

C. C語言實現CAN匯流排報文傳送與接收

這里應該有你想要的。
http://group.ednchina.com/684/Group.aspx?page=10

D. 求CAN通信C程序。SJA1000+PC82C250.晶振是12M的。

這里有兩個晶振,一個是單片機的你選擇12M,一個是sja1000的推薦選擇16M。
給你程序你不一定能用啊,還要和硬體對應啊,比如你的地址確定問題。

這就是網路的程序為什麼大多不能直接使用的原因啊。

給你提供一些思路
1、sja1000初始化
2、發送子程序
3、中斷方式接收

下面是一些程序段
你參考下(已用於產品)

/**********SJA1000初始化***********//
void Init_SJA1000(void)
{
uchar state;
uchar ACRR[4]={0XAA,0XFF,0X22,0X11};// 接收代碼寄存器
uchar AMRR[4]={0xff,0xff,0xff,0xff};// 接收屏蔽寄存器
//uchar AMRR[4]={0x00,0x00,0xff,0xff};// 接收屏蔽寄存器

do// 使用do--while語句確保進入復位模式
{
MODR = 0x09; // 設置MOD.0=1--進入復位模式,以便設置相應的寄存器
state = MODR;
}
while( !(state & 0x01) );

// 對SJA1000部分寄存器進行初始化設置
CDR = 0x88; // CDR為時鍾分頻器,CDR.3=1--時鍾關閉, CDR.7=0---basic CAN, CDR.7=1---Peli CAN
BTR0 = 0x04;//0x31; // 匯流排定時寄存器0 ;匯流排波特率設定
BTR1 = 0x1c;//0x1c; // 匯流排定時寄存器1 ;匯流排波特率設定
IER = 0x01; // IER.0=1--接收中斷使能; IER.1=0--關閉發送中斷使能
OCR = 0xaa; // 配置輸出控制寄存器
CMR = 0x04; // 釋放接收緩沖器

ACR0 = ACRR[0];// 初始化接收代碼寄存器
ACR1 = ACRR[1];
ACR2 = ACRR[2];
ACR3 = ACRR[3];

AMR0 = AMRR[0];// 初始化接收屏蔽寄存器
AMR1 = AMRR[1];
AMR2 = AMRR[2];
AMR3 = AMRR[3];

do// 使用do--while語句確保退出復位模式
{
MODR = 0x08; //MOD.3=0--雙濾波器模式
state = MODR;
}
while( state & 0x01 );
}//////////////////////////////////////

//**********CAN發送數據到CAN-Bus***********//
void CAN_TXD(void)
{
uchar state;

//初始化標示碼頭信息
TX_buffer[0] = 0x88; //.7=0--擴展幀;.6=0--數據幀; .0-.3=100--數據長度為8位元組
// TX_buffer[1] = 0xFF; //本幀信息的ID
//TX_buffer[2] = 0xFF;
TX_buffer[3] = 0xFF;
TX_buffer[4] = 0xFF;

do //查詢SJA1000是否處於接收狀態,當SJA1000不處於接收狀態時才可繼續執行
{
state = SR; //SR為SJA1000的狀態寄存器
}
while( state & 0x10 ); //SR.4=1 正在接收,等待

do //查詢SJA1000是否處於發送完畢狀態
{
state = SR;
}
while(!(state & 0x08)); //SR.3=0,發送請求未處理完,等待直到SR.3=1

do //查詢發送緩沖器狀態
{
state = SR;
}
while(!(state & 0x04)); //SR.2=0,發送緩沖器被鎖。等待直到SR.2=1

//將待發送的一幀數據信息存入SJA1000的相應寄存器中
TBSR0 = TX_buffer[0];
TBSR1 = TX_buffer[1];
TBSR2 = TX_buffer[2];
TBSR3 = TX_buffer[3];
TBSR4 = TX_buffer[4];
TBSR5 = TX_buffer[5];
TBSR6 = TX_buffer[6];
TBSR7 = TX_buffer[7];
TBSR8 = TX_buffer[8];
TBSR9 = TX_buffer[9];
TBSR10 = TX_buffer[10];
TBSR11 = TX_buffer[11];
TBSR12 = TX_buffer[12];

CMR = 0x04; //置位發送請求
}//////////////////////////////////////

//**********中斷接收來自CAN-Bus數據***********//
void inter1_can_rxd( void ) interrupt 0
{
uchar state;

EA = 0; //關CPU中斷
IE0 = 0; //由於是中斷INT1是電平觸發方式,所以需要軟體將INT1的中斷請求標志IE0清零

state = IR; //IR為SJA1000的中斷寄存器
if( state & 0x01) //若IR.0=1--接收中斷
{
RX_buffer[0] = RBSR0;
RX_buffer[1] = RBSR1;
RX_buffer[2] = RBSR2;
RX_buffer[3] = RBSR3;
RX_buffer[4] = RBSR4;
RX_buffer[5] = RBSR5;
RX_buffer[6] = RBSR6;
RX_buffer[7] = RBSR7;
RX_buffer[8] = RBSR8;
RX_buffer[9] = RBSR9;
RX_buffer[10] = RBSR10;
RX_buffer[11] = RBSR11;
RX_buffer[12] = RBSR12;
RXD_flag = 1; //接收標志置位,以便進入接收處理程序

CMR = 0x04; //CMR.2=1--接收完畢,釋放接收緩沖器
state = ALC; //釋放仲裁隨時捕捉寄存器(讀該寄存器即可)
state = ECC; //釋放錯誤代碼捕捉寄存器(讀該寄存器即可)
}
IER = 0x01; // IER.0=1--接收中斷使能
EA = 1; //重新開啟CPU中斷
}//////////////////////////////////////

//********** ***********//

希望對你能有幫助

E. C語言編寫串口通信程序在裸機下運行

單片機你在網上搜一下吧
如果想入門 最好去圖書館借點書看,比較難理解 祝好運了!!
我給你提供以下資料 是網路上找的。

概述
單片機是指一個集成在一塊晶元上的完整計算機系統。盡管它的大部分功能集成在一塊小晶元上,但是它具有一個完整計算機所需要的大部分部件:CPU、內存、內部和外部匯流排系統,目前大部分還會具有外存。同時集成諸如通訊介面、定時器,實時時鍾等外圍設備。而現在最強大的單片機系統甚至可以將聲音、圖像、網路、復雜的輸入輸出系統集成在一塊晶元上。
目錄[隱藏]

單片機介紹
單片機的應用領域
學習應用六大重要部分
單片機學習
常用單片機晶元簡介
從無線電世界到單片機世界
單片機攻擊技術
單片機侵入型攻擊的一般過程

單片機也被稱為微控制器(Microcontroller),是因為它最早被用在工業控制領域。單片機由晶元內僅有CPU的專用處理器發展而來。最早的設計理念是通過將大量外圍設備和CPU集成在一個晶元中,使計算機系統更小,更容易集成進復雜的而對體積要求嚴格的控制設備當中。INTEL的Z80是最早按照這種思想設計出的處理器,從此以後,單片機和專用處理器的發展便分道揚鑣。
早期的單片機都是8位或4位的。其中最成功的是INTEL的8031,因為簡單可靠而性能不錯獲得了很大的好評。此後在8031上發展出了MCS51系列單片機系統。基於這一系統的單片機系統直到現在還在廣泛使用。隨著工業控制領域要求的提高,開始出現了16位單片機,但因為性價比不理想並未得到很廣泛的應用。90年代後隨著消費電子產品大發展,單片機技術得到了巨大的提高。隨著INTEL i960系列特別是後來的ARM系列的廣泛應用,32位單片機迅速取代16位單片機的高端地位,並且進入主流市場。而傳統的8位單片機的性能也得到了飛速提高,處理能力比起80年代提高了數百倍。目前,高端的32位單片機主頻已經超過300MHz,性能直追90年代中期的專用處理器,而普通的型號出廠價格跌落至1美元,最高端的型號也只有10美元。當代單片機系統已經不再只在裸機環境下開發和使用,大量專用的嵌入式操作系統被廣泛應用在全系列的單片機上。而在作為掌上電腦和手機核心處理的高端單片機甚至可以直接使用專用的Windows和Linux操作系統。
單片機比專用處理器更適合應用於嵌入式系統,因此它得到了最多的應用。事實上單片機是世界上數量最多的計算機。現代人類生活中所用的幾乎每件電子和機械產品中都會集成有單片機。手機、電話、計算器、家用電器、電子玩具、掌上電腦以及滑鼠等電腦配件中都配有1-2部單片機。而個人電腦中也會有為數不少的單片機在工作。汽車上一般配備40多部單片機,復雜的工業控制系統上甚至可能有數百台單片機在同時工作!單片機的數量不僅遠超過PC機和其他計算的綜合,甚至比人類的數量還要多。
[編輯本段]單片機介紹

單片機又稱單片微控制器,它不是完成某一個邏輯功能的晶元,而是把一個計算機系統集成到一個晶元上。概括的講:一塊晶元就成了一台計算機。它的體積小、質量輕、價格便宜、為學習、應用和開發提供了便利條件。同時,學習使用單片機是了解計算機原理與結構的最佳選擇。
單片機內部也用和電腦功能類似的模塊,比如CPU,內存,並行匯流排,還有和硬碟作用相同的存儲器件,不同的是它的這些部件性能都相對我們的家用電腦弱很多,不過價錢也是低的,一般不超過10元即可......用它來做一些控制電器一類不是很復雜的工作足矣了。我們現在用的全自動滾筒洗衣機、排煙罩、VCD等等的家電裡面都可以看到它的身影!......它主要是作為控制部分的核心部件。
它是一種在線式實時控制計算機,在線式就是現場控制,需要的是有較強的抗干擾能力,較低的成本,這也是和離線式計算機的(比如家用PC)的主要區別。
單片機是靠程序的,並且可以修改。通過不同的程序實現不同的功能,尤其是特殊的獨特的一些功能,這是別的器件需要費很大力氣才能做到的,有些則是花大力氣也很難做到的。一個不是很復雜的功能要是用美國50年代開發的74系列,或者60年代的CD4000系列這些純硬體來搞定的話,電路一定是一塊大PCB板!但是如果要是用美國70年代成功投放市場的系列單片機,結果就會有天壤之別!只因為單片機的通過你編寫的程序可以實現高智能,高效率,以及高可靠性!
由於單片機對成本是敏感的,所以目前占統治地位的軟體還是最低級匯編語言,它是除了二進制機器碼以上最低級的語言了,既然這么低級為什麼還要用呢?很多高級的語言已經達到了可視化編程的水平為什麼不用呢?原因很簡單,就是單片機沒有家用計算機那樣的CPU,也沒有像硬碟那樣的海量存儲設備。一個可視化高級語言編寫的小程序裡面即使只有一個按鈕,也會達到幾十K的尺寸!對於家用PC的硬碟來講沒什麼,可是對於單片機來講是不能接受的。 單片機在硬體資源方面的利用率必須很高才行,所以匯編雖然原始卻還是在大量使用。一樣的道理,如果把巨型計算機上的操作系統和應用軟體拿到家用PC上來運行,家用PC的也是承受不了的。
可以說,二十世紀跨越了三個「電」的時代,即電氣時代、電子時代和現已進入的電腦時代。不過,這種電腦,通常是指個人計算機,簡稱PC機。它由主機、鍵盤、顯示器等組成。還有一類計算機,大多數人卻不怎麼熟悉。這種計算機就是把智能賦予各種機械的單片機(亦稱微控制器)。顧名思義,這種計算機的最小系統只用了一片集成電路,即可進行簡單運算和控制。因為它體積小,通常都藏在被控機械的「肚子」里。它在整個裝置中,起著有如人類頭腦的作用,它出了毛病,整個裝置就癱瘓了。現在,這種單片機的使用領域已十分廣泛,如智能儀表、實時工控、通訊設備、導航系統、家用電器等。各種產品一旦用上了單片機,就能起到使產品升級換代的功效,常在產品名稱前冠以形容詞——「智能型」,如智能型洗衣機等。現在有些工廠的技術人員或其它業余電子開發者搞出來的某些產品,不是電路太復雜,就是功能太簡單且極易被仿製。究其原因,可能就卡在產品未使用單片機或其它可編程邏輯器件上。
單片機歷史
單片機誕生於20世紀70年代末,經歷了SCM、MCU、SoC三大階段。
1.SCM即單片微型計算機(Single Chip Microcomputer)階段,主要是尋求最佳的單片形態嵌入式系統的最佳體系結構。「創新模式」獲得成功,奠定了SCM與通用計算機完全不同的發展道路。在開創嵌入式系統獨立發展道路上,Intel公司功不可沒。
2.MCU即微控制器(Micro Controller Unit)階段,主要的技術發展方向是:不斷擴展滿足嵌入式應用時,對象系統要求的各種外圍電路與介面電路,突顯其對象的智能化控制能力。它所涉及的領域都與對象系統相關,因此,發展MCU的重任不可避免地落在電氣、電子技術廠家。從這一角度來看,Intel逐漸淡出MCU的發展也有其客觀因素。在發展MCU方面,最著名的廠家當數Philips公司。
Philips公司以其在嵌入式應用方面的巨大優勢,將MCS-51從單片微型計算機迅速發展到微控制器。因此,當我們回顧嵌入式系統發展道路時,不要忘記Intel和Philips的歷史功績。
3.單片機是嵌入式系統的獨立發展之路,向MCU階段發展的重要因素,就是尋求應用系統在晶元上的最大化解決;因此,專用單片機的發展自然形成了SoC化趨勢。隨著微電子技術、IC設計、EDA工具的發展,基於SoC的單片機應用系統設計會有較大的發展。因此,對單片機的理解可以從單片微型計算機、單片微控制器延伸到單片應用系統。
[編輯本段]單片機的應用領域
目前單片機滲透到我們生活的各個領域,幾乎很難找到哪個領域沒有單片機的蹤跡。導彈的導航裝置,飛機上各種儀表的控制,計算機的網路通訊與數據傳輸,工業自動化過程的實時控制和數據處理,廣泛使用的各種智能IC卡,民用豪華轎車的安全保障系統,錄像機、攝像機、全自動洗衣機的控制,以及程式控制玩具、電子寵物等等,這些都離不開單片機。更不用說自動控制領域的機器人、智能儀表、醫療器械了。因此,單片機的學習、開發與應用將造就一批計算機應用與智能化控制的科學家、工程師。
單片機廣泛應用於儀器儀表、家用電器、醫用設備、航空航天、專用設備的智能化管理及過程式控制制等領域,大致可分如下幾個范疇:
1.在智能儀器儀表上的應用
單片機具有體積小、功耗低、控制功能強、擴展靈活、微型化和使用方便等優點,廣泛應用於儀器儀表中,結合不同類型的感測器,可實現諸如電壓、功率、頻率、濕度、溫度、流量、速度、厚度、角度、長度、硬度、元素、壓力等物理量的測量。採用單片機控制使得儀器儀表數字化、智能化、微型化,且功能比起採用電子或數字電路更加強大。例如精密的測量設備(功率計,示波器,各種分析儀)。
2.在工業控制中的應用
用單片機可以構成形式多樣的控制系統、數據採集系統。例如工廠流水線的智能化管理,電梯智能化控制、各種報警系統,與計算機聯網構成二級控制系統等。
3.在家用電器中的應用
可以這樣說,現在的家用電器基本上都採用了單片機控制,從電飯褒、洗衣機、電冰箱、空調機、彩電、其他音響視頻器材、再到電子秤量設備,五花八門,無所不在。
4.在計算機網路和通信領域中的應用
現代的單片機普遍具備通信介面,可以很方便地與計算機進行數據通信,為在計算機網路和通信設備間的應用提供了極好的物質條件,現在的通信設備基本上都實現了單片機智能控制,從手機,電話機、小型程式控制交換機、樓宇自動通信呼叫系統、列車無線通信、再到日常工作中隨處可見的行動電話,集群移動通信,無線電對講機等。
5.單片機在醫用設備領域中的應用
單片機在醫用設備中的用途亦相當廣泛,例如醫用呼吸機,各種分析儀,監護儀,超聲診斷設備及病床呼叫系統等等。
6.在各種大型電器中的模塊化應用
某些專用單片機設計用於實現特定功能,從而在各種電路中進行模塊化應用,而不要求使用人員了解其內部結構。如音樂集成單片機,看似簡單的功能,微縮在純電子晶元中(有別於磁帶機的原理),就需要復雜的類似於計算機的原理。如:音樂信號以數字的形式存於存儲器中(類似於ROM),由微控制器讀出,轉化為模擬音樂電信號(類似於音效卡)。
在大型電路中,這種模塊化應用極大地縮小了體積,簡化了電路,降低了損壞、錯誤率,也方便於更換。
7.單片機在汽車設備領域中的應用
單片機在汽車電子中的應用非常廣泛,例如汽車中的發動機控制器,基於CAN匯流排的汽車發動機智能電子控制器,GPS導航系統,abs防抱死系統,制動系統等等。
此外,單片機在工商,金融,科研、教育,國防航空航天等領域都有著十分廣泛的用途。
[編輯本段]學習應用六大重要部分
單片機學習應用的六大重要部分
一、匯流排:我們知道,一個電路總是由元器件通過電線連接而成的,在模擬電路中,連線並不成為一個問題,因為各器件間一般是串列關系,各器件之間的連線並不很多,但計算機電路卻不一樣,它是以微處理器為核心,各器件都要與微處理器相連,各器件之間的工作必須相互協調,所以需要的連線就很多了,如果仍如同模擬電路一樣,在各微處理器和各器件間單獨連線,則線的數量將多得驚人,所以在微處理機中引入了匯流排的概念,各個器件共同享用連線,所有器件的8根數據線全部接到8根公用的線上,即相當於各個器件並聯起來,但僅這樣還不行,如果有兩個器件同時送出數據,一個為0,一個為1,那麼,接收方接收到的究竟是什麼呢?這種情況是不允許的,所以要通過控制線進行控制,使器件分時工作,任何時候只能有一個器件發送數據(可以有多個器件同時接收)。器件的數據線也就被稱為數據匯流排,器件所有的控制線被稱為控制匯流排。在單片機內部或者外部存儲器及其它器件中有存儲單元,這些存儲單元要被分配地址,才能使用,分配地址當然也是以電信號的形式給出的,由於存儲單元比較多,所以,用於地址分配的線也較多,這些線被稱為地址匯流排。
二、數據、地址、指令:之所以將這三者放在一起,是因為這三者的本質都是一樣的——數字,或者說都是一串『0』和『1』組成的序列。換言之,地址、指令也都是數據。指令:由單片機晶元的設計者規定的一種數字,它與我們常用的指令助記符有著嚴格的一一對應關系,不可以由單片機的開發者更改。地址:是尋找單片機內部、外部的存儲單元、輸入輸出口的依據,內部單元的地址值已由晶元設計者規定好,不可更改,外部的單元可以由單片機開發者自行決定,但有一些地址單元是一定要有的(詳見程序的執行過程)。數據:這是由微處理機處理的對象,在各種不同的應用電路中各不相同,一般而言,被處理的數據可能有這么幾種情況:
1•地址(如MOV DPTR,1000H),即地址1000H送入DPTR。
2•方式字或控制字(如MOV TMOD,#3),3即是控制字。
3•常數(如MOV TH0,#10H)10H即定時常數。
4•實際輸出值(如P1口接彩燈,要燈全亮,則執行指令:MOV P1,#0FFH,要燈全暗,則執行指令:MOV P1,#00H)這里0FFH和00H都是實際輸出值。又如用於LED的字形碼,也是實際輸出的值。
理解了地址、指令的本質,就不難理解程序運行過程中為什麼會跑飛,會把數據當成指令來執行了。
三、P0口、P2口和P3的第二功能用法:初學時往往對P0口、P2口和P3口的第二功能用法迷惑不解,認為第二功能和原功能之間要有一個切換的過程,或者說要有一條指令,事實上,各埠的第二功能完全是自動的,不需要用指令來轉換。如P3.6、P3.7分別是WR、RD信號,當微片理機外接RAM或有外部I/O口時,它們被用作第二功能,不能作為通用I/O口使用,只要一微處理機一執行到MOVX指令,就會有相應的信號從P3.6或P3.7送出,不需要事先用指令說明。事實上『不能作為通用I/O口使用』也並不是『不能』而是(使用者)『不會』將其作為通用I/O口使用。你完全可以在指令中按排一條SETB P3.7的指令,並且當單片機執行到這條指令時,也會使P3.7變為高電平,但使用者不會這么去做,因為這通常會導致系統的崩潰。
四、程序的執行過程: 單片機在通電復位後8051內的程序計數器(PC)中的值為『0000』,所以程序總是從『0000』單元開始執行,也就是說:在系統的ROM中一定要存在『0000』這個單元,並且在『0000』單元中存放的一定是一條指令。
五、堆棧: 堆棧是一個區域,是用來存放數據的,這個區域本身沒有任何特殊之處,就是內部RAM的一部份,特殊的是它存放和取用數據的方式,即所謂的『先進後出,後進先出』,並且堆棧有特殊的數據傳輸指令,即『PUSH』和『POP』,有一個特殊的專為其服務的單元,即堆棧指針SP,每當執一次PUSH指令時,SP就(在原來值的基礎上)自動加1,每當執行一次POP指令,SP就(在原來值的基礎上)自動減1。由於SP中的值可以用指令加以改變,所以只要在程序開始階段更改了SP的值,就可以把堆棧設置在規定的內存單元中,如在程序開始時,用一條MOV SP,#5FH指令,就時把堆棧設置在從內存單元60H開始的單元中。一般程序的開頭總有這么一條設置堆棧指針的指令,因為開機時,SP的初始值為07H,這樣就使堆棧從08H單元開始往後,而08H到1FH這個區域正是8031的第二、三、四工作寄存器區,經常要被使用,這會造成數據的混亂。不同作者編寫程序時,初始化堆棧指令也不完全相同,這是作者的習慣問題。當設置好堆棧區後,並不意味著該區域成為一種專用內存,它還是可以象普通內存區域一樣使用,只是一般情況下編程者不會把它當成普通內存用了。
六、單片機的開發過程: 這里所說的開發過程並不是一般書中所說的從任務分析開始,我們假設已設計並製作好硬體,下面就是編寫軟體的工作。在編寫軟體之前,首先要確定一些常數、地址,事實上這些常數、地址在設計階段已被直接或間接地確定下來了。如當某器件的連線設計好後,其地址也就被確定了,當器件的功能被確定下來後,其控制字也就被確定了。然後用文本編輯器(如EDIT、CCED等)編寫軟體,編寫好後,用編譯器對源程序文件編譯,查錯,直到沒有語法錯誤,除了極簡單的程序外,一般應用模擬機對軟體進行調試,直到程序運行正確為止。運行正確後,就可以寫片(將程序固化在EPROM中)。在源程序被編譯後,生成了擴展名為HEX的目標文件,一般編程器能夠識別這種格式的文件,只要將此文件調入即可寫片。在此,為使大家對整個過程有個認識,舉一例說明:
單片機試驗板ORG 0000H
LJMP START
ORG 040H
START:
MOV SP,#5FH ;設堆棧
LOOP:
NOP
LJMP LOOP ;循環
END ;結束
[編輯本段]單片機學習

目前,很多人對匯編語言並不認可。可以說,掌握用C語言單片機編程很重要,可以大大提高開發的效率。不過初學者可以不了解單片機的匯編語言,但一定要了解單片機具體性能和特點,不然在單片機領域是比較致命的。如果不考慮單片機硬體資源,在KEIL中用C胡亂編程,結果只能是出了問題無法解決!可以肯定的說,最好的C語言單片機工程師都是從匯編走出來的編程者因為單片機的C語言雖然是高級語言,但是它不同於台式機個人電腦上的VC++什麼的單片機的硬體資源不是非常強大,不同於我們用VC、VB等高級語言在台式PC上寫程序畢竟台式電腦的硬體非常強大,所以才可以不考慮硬體資源的問題。還有就是在單片機編程中C語言雖然編程方便,便於人們閱讀,但是在執行效率上是要比匯編語言低10%到20%,所以用什麼語言編寫程序是要看具體用在什麼場合下。總是來說做單片機編程要靈活使用匯編語言與C語言,讓單片機的強大功能以最高是效率展示給用戶。
以8051單片機為例講解單片機的引腳及相關功能;
《單片機引腳圖》
40個引腳按引腳功能大致可分為4個種類:電源、時鍾、控制和I/O引腳。
⒈ 電源:
⑴ VCC - 晶元電源,接+5V;
⑵ VSS - 接地端;
註:用萬用表測試單片機引腳電壓一般為0v或者5v,這是標準的TTL電平。但有時候在單片機程序正在工作時候測試結果並不是這個值而是介於0v-5v之間,其實這是萬用表的響應速度沒這么快而已,在某一個瞬間單片機引腳電壓仍保持在0v或者5v。
⒉ 時鍾:XTAL1、XTAL2 - 晶體振盪電路反相輸入端和輸出端。
⒊ 控制線:控制線共有4根,
⑴ ALE/PROG:地址鎖存允許/片內EPROM編程脈沖
① ALE功能:用來鎖存P0口送出的低8位地址
② PROG功能:片內有EPROM的晶元,在EPROM編程期間,此引腳輸入編程脈沖。
⑵ PSEN:外ROM讀選通信號。
⑶ RST/VPD:復位/備用電源。
① RST(Reset)功能:復位信號輸入端。
② VPD功能:在Vcc掉電情況下,接備用電源。
⑷ EA/Vpp:內外ROM選擇/片內EPROM編程電源。
① EA功能:內外ROM選擇端。
② Vpp功能:片內有EPROM的晶元,在EPROM編程期間,施加編程電源Vpp。
⒋ I/O線
80C51共有4個8位並行I/O埠:P0、P1、P2、P3口,共32個引腳。
P3口還具有第二功能,用於特殊信號輸入輸出和控制信號(屬控制匯流排)
5. P3口第二功能
P30 RXD 串列輸入口
P31 TXD 串列輸出口
P32 INT0 外部中斷0(低電平有效)
P33 INT1 外部中斷1(低電平有效)
P34 T0 定時計數器0
P35 T1 定時計數器1
P36 WR 外部數據存儲器寫選通(低電平有效)
P37 RD 外部數據存儲器讀選通(低電平有效)
[編輯本段]常用單片機晶元簡介
STC單片機
STC公司的單片機主要是基於8051內核,是新一代增強型單片機,指令代碼完全兼容傳統8051,速度快8~12倍,帶ADC,4路PWM,雙串口,有全球唯一ID號,加密性好,抗干擾強.
PIC單片機:
是MICROCHIP公司的產品,其突出的特點是體積小,功耗低,精簡指令集,抗干擾性好,可靠性高,有較強的模擬介面,代碼保密性好,大部分晶元有其兼容的FLASH程序存儲器的晶元.
EMC單片機:
是台灣義隆公司的產品,有很大一部分與PIC 8位單片機兼容,且相兼容產品的資源相對比PIC的多,價格便宜,有很多系列可選,但抗干擾較差.
ATMEL單片機(51單片機):
ATMEl公司的8位單片機有AT89、AT90兩個系列,AT89系列是8位Flash單片機,與8051系列單片機相兼容,靜態時鍾模式;AT90系列單片機是增強RISC結構、全靜態工作方式、內載在線可編程Flash的單片機,也叫AVR單片機.
PHLIPIS 51PLC系列單片機(51單片機):
PHILIPS公司的單片機是基於80C51內核的單片機,嵌入了掉電檢測、模擬以及片內RC振盪器等功能,這使51LPC在高集成度、低成本、低功耗的應用設計中可以滿足多方面的性能要求.
HOLTEK單片機:
台灣盛揚半導體的單片機,價格便宜,種類較多,但抗干擾較差,適用於消費類產品.
TI公司單片機(51單片機):
德州儀器提供了TMS370和MSP430兩大系列通用單片機.TMS370系列單片機是8位CMOS單片機,具有多種存儲模式、多種外圍介面模式,適用於復雜的實時控制場合;MSP430系列單片機是一種超低功耗、功能集成度較高的16位低功耗單片機,特別適用於要求功耗低的場合
松翰單片機(SONIX):
是台灣松翰公司的單片,大多為8位機,有一部分與PIC 8位單片機兼容,價格便宜,系統時鍾分頻可選項較多,有PMW ADC 內振 內部雜訊濾波。缺點RAM空間過小,抗干擾較好。
[編輯本段]從無線電世界到單片機世界
現代計算機技術的產業革命,將世界經濟從資本經濟帶入到知識經濟時代。在電子世界領域,從20世紀中的無線電時代也進入到21世紀以計算機技術為中心的智能化現代電子系統時代。現代電子系統的基本核心是嵌入式計算機系統(簡稱嵌入式系統),而單片機是最典型、最廣泛、最普及的嵌入式系統。

如果對您有幫助,請記得採納為滿意答案,謝謝!祝您生活愉快!

F. stm32CAN通訊怎麼用幾個數據位元組去計算組成小數,能讓CAN發送小數的數據,最好能貼出代碼,感謝!

stm32CAN一個數據段可以發8個位元組 64位,發送小數的話 C語言定義成float(4個位元組)或double (8個位元組),發送時把8個位元組移位拆分到8個發送寄存器中,接收到的8個寄存器再合成到一個64位double 變數中就可以了。

G. 用C語言做通訊錄

這看你是怎樣定義的了。如果你50個同學是用結構體來定義的話就比較容易實現。用二維數組的話,就比較麻煩。
查找名字可以用strcmp(輸入的名字,編好的名字)==0如果相等,就等於查找到你輸入的名字了。記錄它的下標,再輸出它的聯系方式。
下面是一個比較完整的通訊錄代碼,你參考一下啦。(看到專家兩個字,我真沒資格去回答你了,汗)

/*10.3.2源程序*/
/******頭文件(.h)***********/
#include "stdio.h" /*I/O函數*/
#include "stdlib.h" /*標准庫函數*/
#include "string.h"/*字元串函數*/
#include "ctype.h" /*字元操作函數*/
#define M 50 /*定義常數表示記錄數*/
typedef struct /*定義數據結構*/
{
char name[20]; /*姓名*/
char units[30]; /*單位*/
char tele[10]; /*電話*/
}ADDRESS;
/******以下是函數原型*******/
int enter(ADDRESS t[]); /*輸入記錄*/
void list(ADDRESS t[],int n); /*顯示記錄*/
void search(ADDRESS t[],int n); /*按姓名查找顯示記錄*/
int delete(ADDRESS t[],int n); /*刪除記錄*/
int add(ADDRESS t[],int n); /*插入記錄*/
void save(ADDRESS t[],int n); /*記錄保存為文件*/
int load(ADDRESS t[]); /*從文件中讀記錄*/
void display(ADDRESS t[]); /*按序號查找顯示記錄*/
void sort(ADDRESS t[],int n); /*按姓名排序*/
void qseek(ADDRESS t[],int n); /*快速查找記錄*/
void (); /*文件復制*/
void print(ADDRESS temp); /*顯示單條記錄*/
int find(ADDRESS t[],int n,char *s) ; /*查找函數*/
int menu_select(); /*主菜單函數*/
/******主函數開始*******/
main()
{
int i;
ADDRESS adr[M]; /*定義結構體數組*/
int length; /*保存記錄長度*/
clrscr(); /*清屏*/
for(;;)/*無限循環*/
{
switch(menu_select()) /*調用主菜單函數,返回值整數作開關語句的條件*/
{
case 0:length=enter(adr);break;/*輸入記錄*/
case 1:list(adr,length);break; /*顯示全部記錄*/
case 2:search(adr,length);break; /*查找記錄*/
case 3:length=delete(adr,length);break; /*刪除記錄*/
case 4:length=add(adr,length); break; /*插入記錄*/
case 5:save(adr,length);break; /*保存文件*/
case 6:length=load(adr); break; /*讀文件*/
case 7:display(adr);break; /*按序號顯示記錄*/
case 8:sort(adr,length);break; /*按姓名排序*/
case 9:qseek(adr,length);break; /*快速查找記錄*/
case 10:();break; /*復制文件*/
case 11:exit(0); /*如返回值為11則程序結束*/
}
}
}
/*菜單函數,函數返回值為整數,代表所選的菜單項*/
menu_select()
{
char s[80];
int c;
gotoxy(1,25);/*將游標定為在第25行,第1列*/
printf("press any key enter menu......\n");/*提示壓任意鍵繼續*/
getch(); /*讀入任意字元*/
clrscr(); /*清屏*/
gotoxy(1,1);
printf("********************MENU*********************\n\n");
printf(" 0. Enter record\n");
printf(" 1. List the file\n");
printf(" 2. Search record on name\n");
printf(" 3. Delete a record\n");
printf(" 4. add record \n");
printf(" 5. Save the file\n");
printf(" 6. Load the file\n");
printf(" 7. display record on order\n");
printf(" 8. sort to make new file\n");
printf(" 9. Quick seek record\n");
printf(" 10. the file to new file\n");
printf(" 11. Quit\n");
printf("***********************************************\n");
do{
printf("\n Enter you choice(0~11):"); /*提示輸入選項*/
scanf("%s",s); /*輸入選擇項*/
c=atoi(s); /*將輸入的字元串轉化為整型數*/
}while(c11); /*選擇項不在0~11之間重輸*/
return c; /*返回選擇項,主程序根據該數調用相應的函數*/
}
/***輸入記錄,形參為結構體數組,函數值返回類型為整型表示記錄長度*/
int enter(ADDRESS t[])
{
int i,n;
char *s;
clrscr(); /*清屏*/
printf("\nplease input num \n"); /*提示信息*/
scanf("%d",&n); /*輸入記錄數*/
printf("please input record \n"); /*提示輸入記錄*/
printf("name unit telephone\n");
printf("------------------------------------------------\n");
for(i=0;i<n;i++)
{
scanf("%s%s%s",t[i].name,t[i].units,t[i].tele); /*輸入記錄*/
printf("----------------------------------------------\n");
}
return n; /*返回記錄條數*/
}
/*顯示記錄,參數為記錄數組和記錄條數*/
void list(ADDRESS t[],int n)
{
int i;
clrscr();
printf("\n\n*******************ADDRESS******************\n");
printf("name unit telephone\n");
printf("------------------------------------------------\n");
for(i=0;i<n;i++)
printf("%-20s%-30s%-10s\n",t[i].name,t[i].units,t[i].tele);
if((i+1)%10==0) /*判斷輸出是否達到10條記錄*/
{
printf("Press any key continue...\n"); /*提示信息*/
getch(); /*壓任意鍵繼續*/
}
printf("************************end*******************\n");
}
/*查找記錄*/
void search(ADDRESS t[],int n)
{
char s[20]; /*保存待查找姓名字元串*/
int i; /*保存查找到結點的序號*/
clrscr(); /*清屏*/
printf("please search name\n");
scanf("%s",s); /*輸入待查找姓名*/
i=find(t,n,s); /*調用find函數,得到一個整數*/
if(i>n-1) /*如果整數i值大於n-1,說明沒找到*/
printf("not found\n");
else
print(t[i]); /*找到,調用顯示函數顯示記錄*/
}
/*顯示指定的一條記錄*/
void print(ADDRESS temp)
{
clrscr();
printf("\n\n********************************************\n");
printf("name unit telephone\n");
printf("------------------------------------------------\n");
printf("%-20s%-30s%-10s\n",temp.name,temp.units,temp.tele);
printf("**********************end***********************\n");
}
/*查找函數,參數為記錄數組和記錄條數以及姓名s */
int find(ADDRESS t[],int n,char *s)
{
int i;
for(i=0;i<n;i++)/*從第一條記錄開始,直到最後一條*/
{
if(strcmp(s,t[i].name)==0) /*記錄中的姓名和待比較的姓名是否相等*/
return i; /*相等,則返回該記錄的下標號,程序提前結結束*/
}
return i; /*返回i值*/
}
/*刪除函數,參數為記錄數組和記錄條數*/
int delete(ADDRESS t[],int n)
{
char s[20]; /*要刪除記錄的姓名*/
int ch=0;
int i,j;
printf("please deleted name\n"); /*提示信息*/
scanf("%s",s);/*輸入姓名*/
i=find(t,n,s); /*調用find函數*/
if(i>n-1) /*如果i>n-1超過了數組的長度*/
printf("no found not deleted\n"); /*顯示沒找到要刪除的記錄*/
else
{
print(t[i]); /*調用輸出函數顯示該條記錄信息*/
printf("Are you sure delete it(1/0)\n"); /*確認是否要刪除*/
scanf("%d",&ch); /*輸入一個整數0或1*/
if(ch==1) /*如果確認刪除整數為1*/
{
for(j=i+1;j<n;j++) /*刪除該記錄,實際後續記錄前移*/
{
strcpy(t[j-1].name,t[j].name); /*將後一條記錄的姓名拷貝到前一條*/
strcpy(t[j-1].units,t[j].units); /*將後一條記錄的單位拷貝到前一條*/
strcpy(t[j-1].tele,t[j].tele); /*將後一條記錄的電話拷貝到前一條*/
}
n--; /*記錄數減1*/
}
}
return n; /*返回記錄數*/
}
/*插入記錄函數,參數為結構體數組和記錄數*/
int add(ADDRESS t[],int n)/*插入函數,參數為結構體數組和記錄數*/
{
ADDRESS temp; /*新插入記錄信息*/
int i,j;
char s[20]; /*確定插入在哪個記錄之前*/
printf("please input record\n");
printf("************************************************\n");
printf("name unit telephone\n");
printf("--------------------------------------------------\n");
scanf("%s%s%s",temp.name,temp.units,temp.tele); /*輸入插入信息*/
printf("------------------------------------------------\n");
printf("please input locate name \n");
scanf("%s",s); /*輸入插入位置的姓名*/
i=find(t,n,s); /*調用find,確定插入位置*/
for(j=n-1;j>=i;j--) /*從最後一個結點開始向後移動一條*/
{
strcpy(t[j+1].name,t[j].name); /*當前記錄的姓名拷貝到後一條*/
strcpy(t[j+1].units,t[j].units); /*當前記錄的單位拷貝到後一條*/
strcpy(t[j+1].tele,t[j].tele); /*當前記錄的電話拷貝到後一條*/
}
strcpy(t[i].name,temp.name); /*將新插入記錄的姓名拷貝到第i個位置*/
strcpy(t[i].units,temp.units); /*將新插入記錄的單位拷貝到第i個位置*/
strcpy(t[i].tele,temp.tele); /*將新插入記錄的電話拷貝到第i個位置*/
n++; /*記錄數加1*/
return n; /*返回記錄數*/
}
/*保存函數,參數為結構體數組和記錄數*/
void save(ADDRESS t[],int n)
{
int i;
FILE *fp; /*指向文件的指針*/
if((fp=fopen("record.txt","wb"))==NULL) /*打開文件,並判斷打開是否正常*/
{
printf("can not open file\n");/*沒打開*/
exit(1); /*退出*/
}
printf("\nSaving file\n"); /*輸出提示信息*/
fprintf(fp,"%d",n); /*將記錄數寫入文件*/
fprintf(fp,"\r\n"); /*將換行符號寫入文件*/
for(i=0;i<n;i++)
{
fprintf(fp,"%-20s%-30s%-10s",t[i].name,t[i].units,t[i].tele);/*格式寫入記錄*/
fprintf(fp,"\r\n"); /*將換行符號寫入文件*/
}
fclose(fp);/*關閉文件*/
printf("****save success***\n"); /*顯示保存成功*/
}
/*讀入函數,參數為結構體數組*/
int load(ADDRESS t[])
{
int i,n;
FILE *fp; /*指向文件的指針*/
if((fp=fopen("record.txt","rb"))==NULL)/*打開文件*/
{
printf("can not open file\n"); /*不能打開*/
exit(1); /*退出*/
}
fscanf(fp,"%d",&n); /*讀入記錄數*/
for(i=0;i<n;i++)
fscanf(fp,"%20s%30s%10s",t[i].name,t[i].units,t[i].tele); /*按格式讀入記錄*/
fclose(fp); /*關閉文件*/
printf("You have success read data from file!!!\n"); /*顯示保存成功*/
return n; /*返回記錄數*/
}
/*按序號顯示記錄函數*/
void display(ADDRESS t[])
{
int id,n;
FILE *fp; /*指向文件的指針*/
if((fp=fopen("record.txt","rb"))==NULL) /*打開文件*/
{
printf("can not open file\n"); /*不能打開文件*/
exit(1); /*退出*/
}
printf("Enter order number...\n"); /*顯示信息*/
scanf("%d",&id); /*輸入序號*/
fscanf(fp,"%d",&n); /*從文件讀入記錄數*/
if(id>=0&&id<n) /*判斷序號是否在記錄范圍內*/
{
fseek(fp,(id-1)*sizeof(ADDRESS),1); /*移動文件指針到該記錄位置*/
print(t[id]); /*調用輸出函數顯示該記錄*/
printf("\r\n");
}
else
printf("no %d number record!!!\n ",id); /*如果序號不合理顯示信息*/
fclose(fp); /*關閉文件*/
}
/*排序函數,參數為結構體數組和記錄數*/
void sort(ADDRESS t[],int n)
{
int i,j,flag;
ADDRESS temp; /*臨時變數做交換數據用*/
for(i=0;i<n;i++)
{
flag=0; /*設標志判斷是否發生過交換*/
for(j=0;j<n-1;j++)
if((strcmp(t[j].name,t[j+1].name))>0) /*比較大小*/
{
flag=1;
strcpy(temp.name,t[j].name); /*交換記錄*/
strcpy(temp.units,t[j].units);
strcpy(temp.tele,t[j].tele);
strcpy(t[j].name,t[j+1].name);
strcpy(t[j].units,t[j+1].units);
strcpy(t[j].tele,t[j+1].tele);
strcpy(t[j+1].name,temp.name);
strcpy(t[j+1].units,temp.units);
strcpy(t[j+1].tele,temp.tele);
}
if(flag==0)break; /*如果標志為0,說明沒有發生過交換循環結束*/
}
printf("sort sucess!!!\n"); /*顯示排序成功*/
}
/*快速查找,參數為結構體數組和記錄數*/
void qseek(ADDRESS t[],int n)
{
char s[20];
int l,r,m;
printf("\nPlease sort before qseek!\n"); /*提示確認在查找之前,記錄是否已排序*/
printf("please enter name for qseek\n"); /*提示輸入*/
scanf("%s",s); /*輸入待查找的姓名*/
l=0;r=n-1; /*設置左邊界與右邊界的初值*/
while(l<=r) /*當左邊界<=右邊界時*/
{
m=(l+r)/2; /*計算中間位置*/
if(strcmp(t[m].name,s)==0) /*與中間結點姓名欄位做比較判是否相等*/
{
print(t[m]); /*如果相等,則調用print函數顯示記錄信息*/
return ; /*返回*/
}
if(strcmp(t[m].name,s)<0) /*如果中間結點小*/
l=m+1; /*修改左邊界*/
else
r=m-1; /*否則,中間結點大,修改右邊界*/
}
if(l>r) /*如果左邊界大於右邊界時*/
printf("not found\n"); /*顯示沒找到*/
}
/*復制文件*/
void ()
{
char outfile[20]; /*目標文件名*/
int i,n;
ADDRESS temp[M]; /*定義臨時變數*/
FILE *sfp,*tfp; /*定義指向文件的指針*/
clrscr();/*清屏*/
if((sfp=fopen("record.txt","rb"))==NULL) /*打開記錄文件*/
{
printf("can not open file\n"); /*顯示不能打開文件信息*/
exit(1); /*退出*/
}
printf("Enter outfile name,for example c:\\f1\\te.txt:\n"); /*提示信息*/
scanf("%s",outfile); /*輸入目標文件名*/
if((tfp=fopen(outfile,"wb"))==NULL) /*打開目標文件*/
{
printf("can not open file\n"); /*顯示不能打開文件信息*/
exit(1); /*退出*/
}
fscanf(sfp,"%d",&n); /*讀出文件記錄數*/
fprintf(tfp,"%d",n);/*寫入目標文件數*/
fprintf(tfp,"\r\n"); /*寫入換行符*/
for(i=0;i<n;i++)
{
fscanf(sfp,"%20s%30s%10s\n",temp[i].name,temp[i].units,
temp[i].tele); /*讀入記錄*/
fprintf(tfp,"%-20s%-30s%-10s\n",temp[i].name,
temp[i].units,temp[i].tele); /*寫入記錄*/
fprintf(tfp,"\r\n"); /*寫入換行符*/
}
fclose(sfp); /*關閉源文件*/
fclose(tfp); /*關閉目標文件*/
printf("you have success file!!!\n"); /*顯示復製成功*/
}

好好參考一下啦,可能有些函數你還沒學到,找找書就行了。