PROGCONT.RU

Вход Регистрация
О САЙТЕ ГЛАВНАЯ
 

STM32F CAN2 особенность настройки и пример.

 Для тех кто хочет использовать CAN2, делать это стоит если не хватает CAN1 или не возможно его использовать, поясню почему, CAN1 является Master-главный CAN2 Slave-подчинённый. Все настройки банков фильтров делается через CAN1, через CAN2 настраивается его модуль для обмена информации.
 Внизу пример где используются CAN1 и CAN2, между которыми осуществляется обмен данными через трансивер TJA1050, так же в примере имеется код для отправки данных по UART в программу терминал для самопроверки, который можете удалить если в этом нет необходимости.

#include "stm32f10x.h"
void Init_RxMes(CanRxMsg *RxMessage);
void Pause( uint32_t nTime);
CanRxMsg RxMessage_CAN1;
CanRxMsg RxMessage_CAN2;
int main(void)
{
RCC_DeInit();
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
/*Раскомментируйте для проверки через UART или удалите.
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructureU;
GPIO_InitStructureU.GPIO_Pin= GPIO_Pin_9;
GPIO_InitStructureU.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_InitStructureU.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructureU);
GPIO_InitStructureU.GPIO_Pin= GPIO_Pin_10;
GPIO_InitStructureU.GPIO_Mode= GPIO_Mode_IN_FLOATING;
GPIO_Init( GPIOA, &GPIO_InitStructureU);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate= 115200;
USART_InitStructure.USART_WordLength= USART_WordLength_8b;
USART_InitStructure.USART_StopBits= USART_StopBits_1;
USART_InitStructure.USART_Parity= USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
USART_Init( USART1, &USART_InitStructure);
USART_Cmd( USART1, ENABLE);
*/
GPIO_InitTypeDef GPIO_InitStructure;
// Настройка CAN1 RX вывод.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Настройка CAN2 RX вывод.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Настройка CAN1 TX вывод.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Настройка CAN2 TX вывод.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Включаем тактирование CAN1 и CAN2.
RCC_APB1PeriphClockCmd( RCC_APB1Periph_CAN1| RCC_APB1Periph_CAN2, ENABLE);
//Сброс настроек CAN1 и CAN2.
CAN_DeInit( CAN1);
CAN_DeInit( CAN2);
//Структура для настройки CAN1 и CAN2.
CAN_InitTypeDef CAN_InitStructure;
CAN_StructInit( &CAN_InitStructure);
//Установка нужных параметров для работы модулей CAN.
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler =60;
CAN_Init(CAN1, &CAN_InitStructure);
CAN_Init(CAN2, &CAN_InitStructure);
//Структура для настройки банков фильтров.
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//Настройка фильтра для CAN1.
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode= CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale= CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh= 1<<5;
CAN_FilterInitStructure.CAN_FilterIdLow= 0;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 2047<<5;
CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment= 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit( &CAN_FilterInitStructure);
//Настройка фильтра для CAN2.
CAN_FilterInitStructure.CAN_FilterNumber = 14;
CAN_FilterInitStructure.CAN_FilterIdHigh= 2<<5;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 2047<<5;
CAN_FilterInit( &CAN_FilterInitStructure);
//С 0 до 13 банки фильтров принадлежат CAN1, с 14 по 27 CAN2.
CAN_SlaveStartBank( 14);
//Структура для отправки данных CAN1.
CanTxMsg TxMessage_CAN1;
TxMessage_CAN1.StdId= 2;
TxMessage_CAN1.ExtId= 0;
TxMessage_CAN1.RTR= CAN_RTR_DATA;
TxMessage_CAN1.IDE= CAN_ID_STD;
TxMessage_CAN1.DLC= 1;
TxMessage_CAN1.Data[0] = 128;
//Структура для отправки данных CAN2.
CanTxMsg TxMessage_CAN2;
TxMessage_CAN2.StdId= 1;
TxMessage_CAN2.ExtId= 0;
TxMessage_CAN2.RTR= CAN_RTR_DATA;
TxMessage_CAN2.IDE= CAN_ID_STD;
TxMessage_CAN2.DLC= 1;
TxMessage_CAN2.Data[0] = 64;
//Настройка прерывания от принятия данных в FIFO0 для CAN1.
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Настройка прерывания от принятия данных в FIFO0 для CAN2.
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;
NVIC_Init(&NVIC_InitStructure);
//Включаем прерывание.
CAN_ITConfig( CAN1, CAN_IT_FMP0, ENABLE);
CAN_ITConfig( CAN2, CAN_IT_FMP0, ENABLE);
//Основное тело программы.
while(1){
//Отправляем данные через CAN1 и ждем когда данные уйдут.
uint8_t mail_box_number=CAN_Transmit( CAN1, &TxMessage_CAN1);
while( CAN_TransmitStatus( CAN1, mail_box_number)!=CAN_TxStatus_Ok);
//Отправляем данные через CAN2.
CAN_Transmit(CAN2, &TxMessage_CAN2);
Pause( 1000000);
}
}
//Обработчик прерывания от принятия данных модулем CAN1.
void CAN1_RX0_IRQHandler(void)
{
CAN_Receive( CAN1, CAN_FIFO0, &RxMessage_CAN1);
uint8_t filter_number= RxMessage_CAN1.FMI;
uint8_t id_mes= RxMessage_CAN1.StdId;
uint8_t data_mes= RxMessage_CAN1.Data[0];
/*Раскомментируйте для проверки через UART или удалите.
USART_SendData( USART1, filter_number);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
USART_SendData( USART1, id_mes);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
USART_SendData( USART1, data_mes);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
*/
}
//Обработчик прерывания от принятия данных модулем CAN2.
void CAN2_RX0_IRQHandler(void)
{
CAN_Receive( CAN2, CAN_FIFO0, &RxMessage_CAN2);
uint8_t filter_number= RxMessage_CAN2.FMI;
uint8_t id_mes= RxMessage_CAN2.StdId;
uint8_t data_mes= RxMessage_CAN2.Data[0];
/*Раскомментируйте для проверки через UART или удалите.
USART_SendData( USART1, filter_number);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
USART_SendData( USART1, id_mes);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
USART_SendData( USART1, data_mes);
while(!USART_GetFlagStatus( USART1, USART_FLAG_TXE));
*/
}

void Pause( uint32_t nTime){
for( uint32_t i= 0; i< nTime; i++);
}

 Если не используете CAN1 то можете удалить настройки самого модуля, прерывания и его выводов но его тактирование должно быть включено, и не забываем что настройка фильтров для CAN2 делается через CAN1. Так же в коде есть функция CAN_SlaveStartBank( 14), если поменять на CAN_SlaveStartBank( 0) то все банки фильтров с 0 до 27 будут принадлежать CAN2.

Статья №43 Дата:11/04/2019

Комментарии.