首先簡單介紹一下CAN總線,關于CAN總線是誰發明的,CAN總線的歷史,CAN總線的發展,CAN總線的應用場合,這些,通通不說。這里只是以我個人理解,簡單說說CAN通信。CAN總線的端點沒有地址(除非自己在幀里定義地址),CAN總線通信不用地址,用標識符,不是單獨的誰發給誰,而是,你總是發送給整個網絡。然后每個節點都有過濾器,對網絡上的傳播的幀的標識符進行過濾,自己想要什么樣的幀,可以設置自己的過濾器,接收相關的幀信息。如果兩個節點同時發送怎么辦?這個不用我們擔心,CAN控制器會自己仲裁,讓高優先級的幀先發。
然后我們可以了解一下stm32的CAN控制器。
如上圖所示,stm32有兩個can控制器,can1(主),和can2(從),其中過濾器的設置是通過can1來設置,其他工作模式,波特率等,可以各自設置。每個控制器有三個發送郵箱,兩個fifo,每個fifo有三個接收郵箱。
發送:選擇一個空的發送郵箱,把幀信息寫到該發送郵箱的寄存器里,請求發送,控制器就會根據標識符的優先級把幀先后發送出去。
接收:如果接收到的幀的標識符能過過濾表的一系列過濾,該幀信息就會保存在fifo接收郵箱的寄存器里。
過濾器:stm32f407共有28組過濾器,每組過濾器可以設置關聯到fifo0或者fifo1,每組都包括兩個32位存儲器,可以配置成一個32位有位屏蔽功能的標識符過濾器,或者兩個32位完全匹配的標識符過濾器,或者兩個16位有位屏蔽功能的標識符過濾器,或者四個16位完全匹配的標識符過濾器。如下圖所示:
我所說的完全匹配的意思是,接收到的幀的標識符每一位都要跟過濾器對應的位一樣,才能過得了這個過濾器。有位屏蔽功能的意思是一個寄存器放標識符,一個放屏蔽掩碼,屏蔽掩碼為1的位對應的接收到的幀的標識符的位與對應的放標識符的寄存器的位一致,就能通過。
傳輸一位的時間和波特率的計算:
CAN控制器的波特率是由APB時鐘線和CAN位時序寄存器CAN_BTR的TS2[3:0]、TS1[2:0]和BRP[9:0]確定的,其中,TS1[2:0]定義了時間段1占用多少個時間單元,TS2[3:0]定義了時間段2占用多少個時間單元,BRP[9:0]定義對APB1時鐘的分頻。
PS:設置波特率為1M
其中Tpclk為APB1的時鐘周期,假設為
Tpclk = 1/42M
0≦TS1≦7
0≦TS2≦15
0≦BRP≦1021
根據以上數據,有
(TS2+TS1+3)(BRP+1)=42
令BRP=2,有
TS2+TS1=11
令TS1=8,TS2=3
設置步驟:
1. 設置中斷優先級分組(如果之前沒有設置),這個最好一個程序里只在開頭設置一次。
2. 使能相關GPIO時鐘。
3. 選擇相關GPIO引腳的復用功能。
4. 設置相關GPIO引腳為復用模式。
5. 設置相關GPIO引腳的速度,方式。
6. 設置主控制寄存器MCR,進入初始化模式
7. 等待進入初始化模式
8. 設置波特率。
9. 其他設置。
10. 如果要用到中斷,在中斷使能寄存器IER中使能相關中斷響應。
11. 如果要用到中斷,設置相關中斷優先級(NVIC_IP)。
12. 如果要用到中斷,使能相關中斷(NVIC_ISER)。
13. 設置主控制寄存器MCR,進入正常工作模式。
14. 設置FMR,使過濾器組工作在初始化模式。
15. 設置FMR的CAN2SB,確定CAN2的過濾器組從哪一組開始。
16. 設置用到的過濾器組的工作方式。
17. 設置用到的過濾器組的位寬。
18. 給fifo0和fifo2劃分(關聯)過濾組。
19. 禁用用到的過濾器組。
20. 設置過濾器組的標識符,幀類型等。
21. 使能相關過濾器組。
22. 設置FMR,使過濾器組工作在正常模式。
23. 如果要用中斷,編寫中斷服務函數(函數名是固定的)。
24. 中斷服務函數里檢查是哪個中斷。
25. 編寫相應服務程序。
電路請參見本博客:小工具之——CAN收發器
程序:
[plain] view plaincopy/************************************
標題:操作CAN的練習
軟件平臺:IAR for ARM6.21
硬件平臺:stm32f4-discovery
主頻:168M
描述:通過硬件收發器連接CAN1,CAN2
組成一個兩個端點的網絡
CAN1循環發出數據幀
CAN2接收過濾數據幀
用uart把CAN2接收到
的數據幀發到超級終端
author:小船
data:2012-08-14
*************************************/
#include 《stm32f4xx.h》
#include “MyDebugger.h”
#define RECEIVE_BUFFER_SIZE 20
u32 CAN2_receive_buffer[RECEIVE_BUFFER_SIZE][4];
u8 UART_send_buffer[1800];
u8 Consumer = 0;
u8 Producer = 0;
u32 Gb_TImingDelay;
void Delay(uint32_t nTIme);
void TIM7_init();//定時1s
u32 get_rece_data();
void CAN_GPIO_config();
void main ()
{
u32 empty_box;
SysTIck_Config(SystemCoreClock / 1000); //設置systemtick一毫秒中斷
SCB-》AIRCR = 0x05FA0000 | 0x400; //中斷優先級分組 搶占:響應=3:1
MyDebugger_Init();
TIM7_init();
MyDebugger_Message( “nrtesting.。。.。。nr” ,
sizeof(“nrtesting.。。.。。nr”)/sizeof(char) );
CAN_GPIO_config();
RCC-》APB1ENR |= ((1《《25)|(1《《26));//使能CAN1、CAN2時鐘
CAN1-》MCR = 0x00000000;
/*
請求進入初始化模式
禁止報文自動重傳
自動喚醒模式
*/
CAN1-》MCR |= ((1《《0)|(1《《4)|(1《《5));
CAN1-》MCR &= ~(1《《16);//在調試時,CAN照常工作
while(!(CAN1-》MSR & 0xfffffffe)) //等待進入初始化模式
{
MyDebugger_LEDs(orange, on);
}
MyDebugger_LEDs(orange, off);
/*
正常模式
重新同步跳躍寬度(1+1)tq
TS2[2:0]=3
TS1[3:0]=8
BRP[9:0]=2
ps:
tq = (BRP[9:0] + 1) x tPCLK,
tBS2 = tq x (TS2[2:0] + 1),
tBS1 = tq x (TS1[3:0] + 1),
NominalBitTime = 1 × tq+tBS1+tBS2,
BaudRate = 1 / NominalBitTime
波特率設為1M
*/
CAN1-》BTR = ((0《《30)|(0x01《《24)|(3《《20)|(8《《16)|(2《《0));
CAN1-》MCR &= ~(0x00000001);//正常工作模式
CAN2-》MCR = 0x00000000;
/*
請求進入初始化模式
禁止報文自動重傳
自動喚醒模式
*/
CAN2-》MCR |= ((1《《0)|(1《《4)|(1《《5));
CAN2-》MCR &= ~(1《《16);//在調試時,CAN照常工作
while(!(CAN2-》MSR & 0xfffffffe)) //等待進入初始化模式
{
MyDebugger_LEDs(orange, on);
}
MyDebugger_LEDs(orange, off);
/*
正常模式
重新同步跳躍寬度(1+1)tq
TS2[2:0]=3
TS1[3:0]=8
BRP[9:0]=2
ps:
tq = (BRP[9:0] + 1) x tPCLK,
tBS2 = tq x (TS2[2:0] + 1),
tBS1 = tq x (TS1[3:0] + 1),
NominalBitTime = 1 × tq+tBS1+tBS2,
BaudRate = 1 / NominalBitTime
波特率設為1M
*/
CAN2-》BTR = ((0《《30)|(0x01《《24)|(3《《20)|(8《《16)|(2《《0));
CAN2-》IER &= 0x00000000;
/*
FIFO1消息掛號中斷使能
FIFO1滿中斷使能
FIFO1溢出中斷使能
*/
CAN2-》IER |= ((1《《4)|(1《《5)|(1《《6));
NVIC-》IP[65] = 0xa0; //搶占優先級101,響應優先級0
NVIC-》ISER[2] |= (1《《1); //使能中斷線65,也就是can2_rx1中斷
CAN2-》MCR &= ~(0x00000001);//正常工作模式
//總共有28組過濾器
CAN1-》FMR |= 1; //過濾器組工作在初始化模式
CAN1-》FMR &= 0xffffc0ff;//CAN2的過濾器組從14開始
CAN1-》FMR |= (14《《8);
CAN1-》FM1R |= (1《《14);//過濾器組14的寄存器工作在標識符列表模式
//位寬為16位,2個32位分為四個16位寄存器,過濾四個標識符
//CAN1-》FS1R |= (1《《15);//過濾器組15為單個32位寄存器,用于擴展標識符
CAN1-》FFA1R = 0x0fffc000;//0~13號過濾器組關聯到fifo0,14~27號過濾器組關聯到fifo1
CAN1-》FA1R &= ~(1《《14);//禁用過濾器組14
/*
過濾器組0寄存器分為4個十六位過濾器:
標識符列表:
過濾器編號 匹配標準標識符 RTR IDE EXID[17:15]
0 0x7cb(111 1100 1011b) 數據幀 標準標識符 000b
1 0x4ab(100 1010 1011b) 數據幀 標準標識符 000b
2 0x7ab(111 1010 1011b) 數據幀 標準標識符 000b
3 0x40b(100 0000 1011b) 數據幀 標準標識符 000b
*/
CAN1-》sFilterRegister[14].FR1 &= 0x00000000;
CAN1-》sFilterRegister[14].FR2 &= 0x00000000;
CAN1-》sFilterRegister[14].FR1 |= ((0x7cb《《5)|(0《《4)|(0《《3));
CAN1-》sFilterRegister[14].FR1 |= ((0x4ab《《21)|(0《《20)|(0《《19));
CAN1-》sFilterRegister[14].FR2 |= ((0x7ab《《5)|(0《《4)|(0《《3));
CAN1-》sFilterRegister[14].FR2 |= ((0x40b《《21)|(0《《20)|(0《《19));
CAN1-》FA1R |= (1《《14);//使能過濾器組14
CAN1-》FMR &= ~1; //過濾器組正常工作
while(1)
{
/*
選擇空的發送郵箱:
標準標識符0x7ab(111 1010 1011b)
數據幀
不使用擴展標識符
*/
if( CAN1-》TSR & ((1《《26)|(1《《27)|(1《《28)) )
{
empty_box = ((CAN1-》TSR》》24) & 0x00000003);
CAN1-》sTxMailBox[empty_box].TIR = (0x7ab《《21);
CAN1-》sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1-》sTxMailBox[empty_box].TDTR |= 0x00000008;//發送數據長度為8
CAN1-》sTxMailBox[empty_box].TDLR = 0x12345678;
CAN1-》sTxMailBox[empty_box].TDHR = 0x9abcdef0;
CAN1-》sTxMailBox[empty_box].TIR |= (1《《0);//請求發送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
選擇空的發送郵箱:
標準標識符0x4ab(100 1010 1011b)
數據幀
不使用擴展標識符
*/
if( CAN1-》TSR & ((1《《26)|(1《《27)|(1《《28)) )
{
empty_box = ((CAN1-》TSR》》24) & 0x00000003);
CAN1-》sTxMailBox[empty_box].TIR = (0x4ab《《21);
CAN1-》sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1-》sTxMailBox[empty_box].TDTR |= 0x00000008;//發送數據長度為8
CAN1-》sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1-》sTxMailBox[empty_box].TDHR = 0x9abcdef0;
CAN1-》sTxMailBox[empty_box].TIR |= (1《《0);//請求發送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
選擇空的發送郵箱:
標準標識符0x7cb(100 1010 1011b)
數據幀
不使用擴展標識符
*/
if( CAN1-》TSR & ((1《《26)|(1《《27)|(1《《28)) )
{
empty_box = ((CAN1-》TSR》》24) & 0x00000003);
CAN1-》sTxMailBox[empty_box].TIR = (0x7cb《《21);
CAN1-》sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1-》sTxMailBox[empty_box].TDTR |= 0x00000006;//發送數據長度為6
CAN1-》sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1-》sTxMailBox[empty_box].TDHR = 0x00009abc;
CAN1-》sTxMailBox[empty_box].TIR |= (1《《0);//請求發送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
選擇空的發送郵箱:
標準標識符0x40b(100 0000 1011b)
數據幀
不使用擴展標識符
*/
if( CAN1-》TSR & ((1《《26)|(1《《27)|(1《《28)) )
{
empty_box = ((CAN1-》TSR》》24) & 0x00000003);
CAN1-》sTxMailBox[empty_box].TIR = (0x40b《《21);
CAN1-》sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1-》sTxMailBox[empty_box].TDTR |= 0x00000004;//發送數據長度為4
CAN1-》sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1-》sTxMailBox[empty_box].TDHR = 0x00000000;
CAN1-》sTxMailBox[empty_box].TIR |= (1《《0);//請求發送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
}
}
/****************************************
函數名:CAN_GPIO_config
參數:無
返回值:無
功能:設置CAN1,2控制器用到IO口
CAN1_TX---------PD1
CAN1_RX---------PB8
CAN2_TX---------PB13
CAN2_RX---------PB5
****************************************/
void CAN_GPIO_config()
{
RCC-》AHB1ENR |= ((1《《1) | (1《《3));//使能GPIOB、D時鐘
GPIOB-》AFR[0] |= 0x00900000; //AF9
GPIOB-》AFR[1] |= 0x00900009;
GPIOD-》AFR[0] |= 0x00000090;
GPIOB-》MODER &= 0xF3FCF3FF; //第二功能
GPIOB-》MODER |= 0x08020800;
GPIOD-》MODER &= 0xFFFFFFF3;
GPIOD-》MODER |= 0x00000008;
GPIOB-》OSPEEDR &= 0xF3FCF3FF; //50M
GPIOB-》OSPEEDR |= 0x08020800;
GPIOD-》OSPEEDR &= 0xFFFFFFF3;
GPIOD-》OSPEEDR |= 0x00000008;
GPIOB-》PUPDR &= 0xF3FCF3FF; //上拉
GPIOB-》PUPDR |= 0x04010400;
GPIOD-》PUPDR &= 0xFFFFFFF3;
GPIOD-》PUPDR |= 0x00000004;
}
/****************************************
函數名:CAN2_RX1_IRQHandler
參數:無
返回值:無
功能:CAN2fifo1接收中斷處理
把信息存進循環隊列
****************************************/
void CAN2_RX1_IRQHandler()
{
if(CAN2-》RF1R & (0x00000003))//接收到新的消息,fifo1非空
{
Producer++;
if(Producer == RECEIVE_BUFFER_SIZE)Producer = 0;
if(Producer != Consumer)
{
CAN2_receive_buffer[Producer][0] = CAN2-》sFIFOMailBox[1].RIR;
CAN2_receive_buffer[Producer][1] = CAN2-》sFIFOMailBox[1].RDTR;
CAN2_receive_buffer[Producer][2] = CAN2-》sFIFOMailBox[1].RDLR;
CAN2_receive_buffer[Producer][3] = CAN2-》sFIFOMailBox[1].RDHR;
}
else
{
if(Producer == 0)Producer = RECEIVE_BUFFER_SIZE;
Producer--;
MyDebugger_LEDs(blue, on);
}
CAN2-》RF1R |= (1《《5);//釋放郵箱
}
if(CAN2-》RF1R & (1《《3))//fifo0滿
{
MyDebugger_LEDs(red, on);
CAN2-》RF1R &= ~(1《《3);
}
if(CAN2-》RF1R & (1《《4))//fifo0溢出
{
MyDebugger_LEDs(red, on);
CAN2-》RF1R &= ~(1《《4);
}
}
/****************************************
函數名:TIM7_init
參數:無
返回值:無
功能:初始化定時器7
作1s定時用
****************************************/
void TIM7_init()
{
RCC-》APB1ENR |= (1《《5); //打開TIM7時鐘
TIM7-》PSC = 8399; //對時鐘84M進行8400分頻,使得計數頻率為10k
TIM7-》ARR = 10000; //定時一秒
TIM7-》CNT = 0; //清空計數器
TIM7-》CR1 |= (1《《7); //自動重裝載預裝載使能
TIM7-》DIER |= 1; //使能中斷
NVIC-》IP[55] = 0xe0;
NVIC-》ISER[1] |= (1《《(55-32));
TIM7-》CR1 |= 1; //開始計時
}
/****************************************
函數名:TIM7_IRQHandler
參數:無
返回值:無
功能:定時器7中斷處理
1s定時到
把can2收到的信息轉換格式
用usrt發送到超級終端顯示
****************************************/
void TIM7_IRQHandler(void)
{
u32 length;
if(TIM7-》SR)
{
length = get_rece_data();
MyDebugger_Message( UART_send_buffer, length );
TIM7-》SR &= ~(0x0001);
}
}
/****************************************
函數名:get_rece_data
參數:無
返回值:length 整理后要發送數據的長度
功能:把循環隊列的信息取出
進行格式轉換
把信息存到uart發送緩沖區
****************************************/
u32 get_rece_data()
{
u8 filter_No;
u8 Data_length;
char i;
u32 length = 0;
const char ascii[16] = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’,
‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’};
while(1)
{
if(Producer != Consumer)
{
Consumer++;
if(Consumer == RECEIVE_BUFFER_SIZE)Consumer=0;
UART_send_buffer[length++] = ‘n’;
UART_send_buffer[length++] = ‘r’;
//Filter No.xx
UART_send_buffer[length++] = ‘F’;
UART_send_buffer[length++] = ‘i’;
UART_send_buffer[length++] = ‘l’;
UART_send_buffer[length++] = ‘t’;
UART_send_buffer[length++] = ‘e’;
UART_send_buffer[length++] = ‘r’;
UART_send_buffer[length++] = ‘ ’;
UART_send_buffer[length++] = ‘N’;
UART_send_buffer[length++] = ‘o’;
UART_send_buffer[length++] = ‘。’;
filter_No = (CAN2_receive_buffer[Consumer][1]》》8) & 0x000000ff;
UART_send_buffer[length++] = filter_No%100/10 + ‘0’;
UART_send_buffer[length++] = filter_No%10 + ‘0’;
UART_send_buffer[length++] = ‘n’;
UART_send_buffer[length++] = ‘r’;
上一篇:STM32開發板實驗箱8位獨立按鍵測試學習
下一篇:淺談STM32的FSMC的TFT筆記
推薦閱讀
史海拾趣
ABCO公司深知產品質量是企業生存的根本。因此,公司建立了一套嚴格的質量管理體系,從原材料采購到產品生產、檢測、出廠等各個環節都進行嚴格把控。同時,公司還注重持續改進,不斷優化生產流程,提高生產效率,確保產品質量始終保持在行業前列。
隨著環保意識的日益增強,AIM積極響應國家的環保政策,將綠色生產理念融入公司的日常運營中。公司投入大量資金引進環保設備和技術,優化生產流程,減少污染物排放。同時,AIM還推出了一系列環保型電子產品,滿足了消費者對綠色產品的需求。
作為一家具有社會責任感的企業,EnerSys積極參與社區回饋活動,并致力于可持續發展。公司不僅在業務上取得了顯著成就,還通過參與各種公益活動,回饋社會。同時,EnerSys還關注環境保護和可持續發展問題,努力減少生產過程中的能源消耗和廢物排放。這些舉措不僅提升了EnerSys的品牌形象,也為公司的長遠發展奠定了基礎。
請注意,以上故事框架為概述性質,并未詳細展開每個故事的細節。在實際撰寫時,您可以根據這些框架進一步補充和完善具體內容。
在追求經濟效益的同時,C.K Magma公司也積極履行社會責任。他們注重綠色發展和可持續經營,通過采用環保材料和工藝、優化生產過程等方式,降低產品對環境的影響。此外,公司還積極參與公益事業,為社會做出貢獻。這些舉措不僅提升了公司的社會形象,也為公司的長遠發展提供了有力保障。
這五個故事展示了C.K Magma公司在電子行業中的發展歷程和取得的成就。通過技術突破、市場拓展、國際合作、創新產品和綠色發展等方面的努力,公司逐漸在行業中嶄露頭角,成為了一家具有影響力和競爭力的企業。
隨著全球環保意識的不斷提高,電子行業對環保材料的需求也日益增長。CUI公司敏銳地抓住了這一市場機遇,積極投入研發,成功開發出了一種綠色環保型的碘化亞銅生產工藝。這種工藝不僅降低了生產過程中的能耗和排放,而且提高了產品的純度和質量。通過推廣這一工藝,CUI公司不僅贏得了客戶的青睞,也為行業的綠色發展做出了積極貢獻。
百蓉公司不滿足于僅在國內市場發展,開始積極拓展國際市場。他們參加了多個國際電子展覽,與多家國際知名企業建立了合作關系。通過深入了解不同國家和地區的市場需求,百蓉針對性地推出了符合當地消費者需求的產品,逐漸在國際市場上占據了一席之地。
#include <config.h> #include <version.h> /* 這段代碼的主要作用是初始化硬件設備、建立內存空間的映射圖,從而將系統的軟硬件環境帶到一個合適的狀態,以便為最終調用操作系統內核準備好正確的環境 */ #if defined(CONFIG_OMAP1610) ...… 查看全部問答∨ |
我最近在搞wince usb function 驅動,在/WINCE600/PUBLIC/.../DRIVER/usbfn里面是usb function驅動部分的代碼,里面有一個controler文件夾,是從驅動的控制器源代碼,這部分代碼負責智能手機作為電腦的從設備,在串口,網卡,存儲,打印4個client之 ...… 查看全部問答∨ |
1 引言 大多數非FPGA類型的、高密度IC(如CPU)對去耦電容都有非常明確的要求。由于這些器件僅為執行特定的任務而設計,所以其電源電流需求是固定的,僅在一定范圍內有所波動。 &nbs ...… 查看全部問答∨ |
也許這個帖子不該放在這個版塊,但是感覺這個版塊非常活躍,自己也在學習STM32,曾多次受到版主及眾位前輩的多次指點,望版主見諒。小弟現在遇到了技術以外更為嚴重的困惑,希望大家能夠指點迷津。 小弟現在研二, ...… 查看全部問答∨ |
有沒有人用Mc13224或者其他FS的芯片做過ZigBee定位系統? 我遇到了點問題,我用的是LQI計算距離的,因為不知道怎么獲得RSSI。 4個參考節點的時候,有時有數據丟失,但基本有定位功能。節點多了就不行了,求高手幫忙,有項目經費支持。… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 課隨你變 票選你選型覺得最困難的元器件,干貨越多禮品越大!
- 【已結束】R&S 直播【PCI Express Gen 3 一致性測試(含demo演示)】
- 免費測評樂鑫ESP32-C3-DevKitM-1
- 【分享成長,10月有獎】EEWORLD優秀主題/回復第15期活動開始啦!!!
- 下載贏禮 | 雅特生 PMBus 接口非隔離數字 DC-DC 轉換器
- 電機小課堂 | 單相無刷電機無感控制,小功率電機驅動應用中的最佳解決方案
- 直播已結束【安森美半導體超低功耗 RSL10 藍牙 SoC 開發板詳解】
- 2021年STM32中國峰會暨粉絲狂歡節 報名啦!
- 有獎直播|TI 符合 USB 2.0 標準的最新隔離器件
- 下載資料贏好禮!看Vicor模塊化電源解決方案如何推動創新