Hello! Working code for STM32F103C8T6 witn CAN and 2 filters enabled:
Code: Select all
/*
* CAN example for STM32F103 in normal mode (125/100/50 KBaud) with 2 working filters
*
*/
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
const char prog_name[] = "\r\nSTM32F103-CB-MAXXIR-V12 BB00-minimum CAN 50kbps hello v1.0 17/07/2017\r\n";
BaseSequentialStream* _uart3 = (BaseSequentialStream*) &SD3;
//***************CAN: BEGIN
/*
* Internal loopback mode, 500KBaud, automatic wakeup, automatic recover
* from abort mode.
* See section 22.7.7 on the STM32 reference manual.
*/
/*
static const CANConfig cancfg = {
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
CAN_BTR_TS1(8) | CAN_BTR_BRP(6) !! - error must be CAN_BTR_BRP(5)
};
*/
//Using online calculator: http://www.bittiming.can-wiki.info/
/*
With:
Clock rate: 36Mhz (APB1 clock = SYSCLK div 2)
Sample point at: 75% (The same manner as my MCHP M2515 CAN Controller)
SJW: 1
*/
//For CAN 125KBaud (must read from CAN_BTR: 0x003A0011) - if need LOOPBACK add CAN_BTR_LBKM | ..
/*
static const CANConfig cancfg = {
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
CAN_BTR_SJW(0) | CAN_BTR_TS2(3) |
CAN_BTR_TS1(10) | CAN_BTR_BRP(17)
};
*/
//For CAN 100KBaud (must read from CAN_BTR: 0x004D0011) - if need LOOPBACK add CAN_BTR_LBKM | ..
/*
static const CANConfig cancfg = {
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
CAN_BTR_SJW(0) | CAN_BTR_TS2(4) |
CAN_BTR_TS1(13) | CAN_BTR_BRP(17)
};
*/
//For CAN 50KBaud (must read from CAN_BTR: 0x003a002c) - if need LOOPBACK add CAN_BTR_LBKM | ..
//Clock rate: 36Mhz (APB1 clock = SYSCLK div 2)
//Sample point at: 75%
//SJW=1,TS1=11,TS2=4,PRE=45 => 36000Khz/16/45=50KBaud
static const CANConfig cancfg = {
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
CAN_BTR_SJW(0) | CAN_BTR_TS2(3) |
CAN_BTR_TS1(10) | CAN_BTR_BRP(44)
};
/*
* Receiver thread.
*/
static THD_WORKING_AREA(can_rx_wa, 256);
static THD_FUNCTION(can_rx, p) {
event_listener_t el;
CANRxFrame rxmsg;
(void)p;
chRegSetThreadName("receiver");
chEvtRegister(&CAND1.rxfull_event, &el, 0);
while (true) {
if (chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100)) == 0)
continue;
while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == MSG_OK) {
/* Process message.*/
chprintf(_uart3, ">>>RTR: %d, IDE: %d, EID: 0x%08x, DLC: %d: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\r\n",\
rxmsg.RTR,\
rxmsg.IDE, rxmsg.EID, rxmsg.DLC,\
rxmsg.data8[0], rxmsg.data8[1], rxmsg.data8[2], rxmsg.data8[3],\
rxmsg.data8[4], rxmsg.data8[5], rxmsg.data8[6], rxmsg.data8[7]\
);
palTogglePad(GPIOB, GPIOB_LED1);
}
}
chEvtUnregister(&CAND1.rxfull_event, &el);
}
/*
* Transmitter thread.
*/
static THD_WORKING_AREA(can_tx_wa, 256);
static THD_FUNCTION(can_tx, p) {
CANTxFrame txmsg;
(void)p;
chRegSetThreadName("transmitter");
txmsg.IDE = CAN_IDE_EXT;
txmsg.EID = 0x01234567;
txmsg.RTR = CAN_RTR_DATA;
txmsg.DLC = 8;
txmsg.data32[0] = ST2S(chVTGetSystemTime());
txmsg.data32[1] = 0x12345678;
//txmsg.data32[0] = 0x55AA55AA;
//txmsg.data32[1] = 0x00FF00FF;
while (true) {
txmsg.data32[0] = ST2S(chVTGetSystemTime());
txmsg.data32[1] = 0x12345678;
if (palReadPad(GPIOA, GPIOA_BUTTON1))
{
//Button1 pressed send eid = 0x01234568
txmsg.EID = 0x01234568;
}
else
{
//Button1 unpressed send eid = 0x01234567
txmsg.EID = 0x01234567;
}
canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg, MS2ST(100));
chThdSleepMilliseconds(1000);
}
}
//***************CAN: END
/*Look at Figure 229. Filter bank scale configuration - register organization (STM32F10x reference manual)*/
/*0b100 - Data with EID or (0b110 - RemoteFrame with EID)*/
#define set_can_eid_data(x) ((x << 3)|0b100)
/*0b110 - Mask enable for EID/SID and DATA/RTR*/
#define set_can_eid_mask(x) ((x << 3)|0b110)
/*
* Application entry point.
*/
//#define CAN_REMAP //Comment if not used CAN pins remapping
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
/*
* Activates the serial driver 3 using the driver default configuration.
*/
sdStart(&SD3, NULL);
//Type prog metrics && sysclk_speed
chprintf(_uart3, prog_name);
chprintf(_uart3, "STM32_SYSCLK: %UHz\r\n", STM32_SYSCLK);
#ifndef CAN_REMAP
//var1. Setup CAN pins for STM32F103: CAN_RX = PA11, CAN_TX =PA12
palSetPadMode(GPIOA, 12, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(GPIOA, 11, PAL_MODE_INPUT);
#else
//var2.Setup Can pins for STM32F103 AFIO CAN Remap: CAN_RX = PB8, CAN_TX =PB9
AFIO->MAPR |= AFIO_MAPR_CAN_REMAP_REMAP2; // CANRX mapped to PB8, CANTX mapped to PB9
palSetPadMode(GPIOB, 9, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(GPIOB, 8, PAL_MODE_INPUT);
#endif
/*
* Activates the CAN driver 1.
*/
//Receive all frames on CAN1
//canSTM32SetFilters(&CAND1, 0xE, 0, NULL); /*0xE for STM32F103 - no filters assigned to CAN2 (only CAN1 present), dont filter anything */
//Disable CAN filtering for now until we can verify proper operation / settings.
/*
*The same manner we can set up to 14 filters (STM32F103)
*For example to use 2 EID Data filter to 2 CAN RX FIFO:
*/
//Set filers #1-#2 for eid = 0x01234567 || eid = 0x01234568
CANFilter can_filter_12[2] = {\
/* Assign filter #1 32bit mask eid=0x01234567 to FIFO 0 */
{1, 0, 1, 0, set_can_eid_data(0x01234567), set_can_eid_mask(0x1FFFFFFF)},\
/* Assign filter #2 32bit mask eid=0x01234568 to FIFO 1 */
{2, 0, 1, 1, set_can_eid_data(0x01234568), set_can_eid_mask(0x1FFFFFFF)}\
};
//Set 2 filters from total 14(0xE)
canSTM32SetFilters(&CAND1, 0xE, 2, &can_filter_12[0]);
canStart(&CAND1, &cancfg);
/*
* Starting the transmitter and receiver threads.
*/
chThdCreateStatic(can_rx_wa, sizeof(can_rx_wa), NORMALPRIO + 7, can_rx, NULL);
chThdCreateStatic(can_tx_wa, sizeof(can_tx_wa), NORMALPRIO + 7, can_tx, NULL);
/*
* Normal main() thread activity, in this demo it does nothing except
* sleeping in a loop and check the button state.
*/
while (true) {
chThdSleepMilliseconds(1000);
}
}
First: the bits for the filter id and the mask must be pre-shifted
Code: Select all
/*0b100 - Data with EID or (0b110 - RemoteFrame with EID)*/
#define set_can_eid_data(x) ((x << 3)|0b100)
/*0b110 - Mask enable for EID/SID and DATA/RTR*/
#define set_can_eid_mask(x) ((x << 3)|0b110)
Second: (That is important for STM32F10x. Don't know how it for STM32F042x) you must assign total count of filters for CAN1 module
Code: Select all
canSTM32SetFilters(&CAND1, 0xE, 2, &can_filter_12[0])
- here 14 filters for CAN1 and 2 from them working.
I hope this helps you.