Red de conocimiento informático - Material del sitio web - Cómo operar el CAN esclavo de STM32F105

Cómo operar el CAN esclavo de STM32F105

#include "can.h"

#include "led.h"

#include "delay.h"

# incluir "usart.h"

///////////////////////////////////// // /////////////////////////////////////////////////

//Este programa es solo para aprendizaje y no puede usarse para ningún otro propósito sin el permiso del autor

//Placa de desarrollo ALIENTEK Battleship STM32

// Código del controlador CAN

p>

//Átomo en punto @ALIENTEK

//Foro técnico: www.openedv.com

//Fecha de modificación: 2012 /9/11

//Versión: V1.0

//Copyright, se investigará la piratería.

//Copyright(C) Guangzhou Xingyi Electronic Technology Co., Ltd. 2009-2019

//Todos los derechos reservados

////// / ///////////////////////////////////////////////// //// ////////////////////////////////inicialización CAN

//tsjw: resincronización salto Unidad de tiempo Rango: 1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq

//tbs2: Unidad de tiempo del período de tiempo 2. Rango: 1~8;

//tbs1: Tiempo. período Unidad de tiempo de 1. Rango: 1~16; CAN_BS1_1tq ~CAN_BS1_16tq

//brp: Divisor de velocidad en baudios Rango: 1~1024; (brp)*tpclk1

//Tenga en cuenta que ninguno de los parámetros anteriores se puede establecer en 0; de lo contrario, será caótico.

//Baud rate=Fpclk1/((tsjw+ tbs1+tbs2)*brp);

//modo:0, modo normal; 1, modo loopback;

//El reloj de Fpclk1 se establece en 36M durante la inicialización. Establezca CAN_Normal_Init(1,8,7,5,1);

//La velocidad en baudios es: 36 M/((1+8+7)*5)=450 Kbps

//Valor de retorno: 0, inicialización correcta;

// Otros, inicialización fallida;

/////////////////// ////////////////////////////////////CAN1///////////// //// /////////////////////////////////////

u8 CAN_Mode_Init (u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, modo u8)

{

GPIO_InitTypeDef GPIO_InitStructure

CAN_InitTypeDef CAN_InitStructure;

CAN_FilterInitTypeDef CAN_FilterInitStructure;

#if CAN_RX0_INT_ENABLE

NVIC_InitTypeDef NVIC_InitStructure;

#endif

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);/ /Habilitar reloj PORTD, Habilitar función de reloj de multiplexación

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//Habilitar reloj CAN1

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure. GPIO_Speed ​​= GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //multiplex push-pull

GPIO_Init(GPIOA, &GPIO_InitStructure)

; //Inicializar IO

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU //Entrada desplegable

GPIO_Init(GPIOA, &GPIO_InitStructure) ; //Inicializar IO

//GPIO_PinRemapConfig(GPIO_Remap2_CAN1,ENABLE);

//Configuración de la unidad CAN

CAN_InitStructure.CAN_TTCM=DISABLE; disparador de tiempo Modo de comunicación //

CAN_InitStructure.CAN_ABOM=DISABLE; //Gestión automática fuera de línea del software //

CAN_InitStructure.CAN_AWUM=DISABLE //El modo de suspensión se activa a través del software (borrar) CAN-> bit SLEEP de MCR) //

CAN_InitStructure.CAN_NART=ENABLE; //Prohibir la transmisión automática de mensajes //

CAN_InitStructure.CAN_RFLM=DISABLE //Los mensajes no son bloqueado, nuevo Sobrescribe el antiguo //

CAN_InitStructure.CAN_TXFP=DISABLE; //La prioridad está determinada por el identificador del mensaje //

CAN_InitStructure.CAN_Mode= //Configuración del modo; : modo :0, modo normal; 1, modo loopback; //

//Establece la velocidad en baudios

CAN_InitStructure.CAN_SJW=tsjw //El ancho de salto de resincronización (Tsjw) tsjw +1 unidad de tiempo CAN_SJW_1tq CAN_SJW_3tq CAN_SJW_4tq

CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1 unidad de tiempo CAN_BS1_1tq ~CAN_BS1_16tq

CAN_InitStructure.CAN_BS2=t bs2;// Tbs2 =tbs2+1 unidad de tiempo CAN_BS2_1tq ~ CAN_BS2_8tq

CAN_InitStructure.CAN_Prescaler=brp; //El coeficiente de división de frecuencia (Fdiv) es brp+1 //

CAN_Init(CAN1, &CAN_InitStructure; //32 bits

CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////ID de 32 bits

CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;

C

AN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//MASCARA de 32 bits

CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;

CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//El filtro 0 está asociado con FIFO0

CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //Activar filtro 0

CAN_FilterInit(&CAN_FilterInitStructure);//Inicialización del filtro

#if CAN_RX0_INT_ENABLE

CAN_ITConfig( CAN1 ,CAN_IT_FMP0,ENABLE); // Se permite la interrupción del registro de mensajes FIFO0

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1 // La prioridad principal es 1 p>

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // La prioridad secundaria es 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

#endif

return 0;

}

#if CAN_RX0_INT_ENABLE //Habilitar interrupción RX0

//Función de servicio de interrupción

void CAN1_RX0_IRQHandler(void)

{

CanRxMsg RxMessage;

int i=0;

CAN_Receive(CAN1 , 0, &RxMessage);

Can_Send_Msg(RxMessage.Data,8);

}

#endif

//puede enviar Un conjunto de datos (formato fijo: ID es 0X12, marco estándar, marco de datos)

//len: longitud de datos (máximo 8)

//msg: puntero de datos, máximo es de 8 bytes.

//Valor de retorno: 0, éxito;

// Otros, error;

u8 Can_Send_Msg(u8* msg,u8 len)

{

u8 mbox;

u16 i=0;

CanTxMsg TxMessage;

TxMessage .StdId =0x12; // El identificador estándar es 0

TxMessage.ExtId=0x12; // Establece el identificador extendido (29 bits)

TxMessage.IDE=0; identificador

TxMessage.RTR=0; // El tipo de mensaje es trama de datos, 8 bits por trama

TxMessage.DLC=len // Envía dos tramas de informaciónp>

for(i=0;i<8;i++)

TxMessage.Data[i]=msg[i]; // Información del primer cuadro

mbox= CAN_Transmit(CAN1, &TxMessage

i=0;

while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;

if(i>=0XFFF)return 1;

return 0;

}

//el puerto puede recibir la consulta de datos

//buf: área del búfer de datos;

//Valor de retorno: 0, no se recibieron datos;

//Otros, longitud de los datos recibidos;

p>

u8 Can_Receive_Msg(u8 *buf)

{

u32 i;

CanRxMsg RxMessage;

if( CAN_MessagePending (CAN1,CAN_FIFO0)==0)return 0; //No se recibieron datos, salga directamente

CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//Leer datos

para ( i=0;i<8;i++)

buf[i]=RxMessage.Data[i];

return RxMessage.DLC

}

///////////////////////////////////////////// / ////////CAN2///////////////////////////////////////// ///// ///////////

u8 CAN2_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 modo)

{

GPIO_InitTypeDef GPIO_InitStructure;

CAN_InitTypeDef CAN_InitStructure;

CAN_FilterInitTypeDef CAN_FilterInitStructure;

#if CAN_RX2_INT_ENABLE

NVIC_InitTypeDef NVIC_InitStructure;

#endif

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);//Habilitar reloj PORTB

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//Habilitar reloj CAN2

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;

GPIO_InitStructure.GPIO_Speed ​​​​= GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP //Múltiples push-pull

>

GPIO_Init(GPIOB, &GPIO_InitStructure); //Inicializar IO

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU //Entrada desplegable

GPIO_Init(GPIOB, &GPIO_InitStructure);//Inicializar IO

//GPIO_PinRemapConfig(GPIO_Remap_CAN2,ENABLE);

//Configuración de la unidad CAN

CAN_InitStructure .CAN_TTCM=DISABLE; //Modo de comunicación activado sin tiempo//

CAN_InitStructure.CAN_ABOM=DISABLE //Gestión automática del software fuera de línea//

CAN_InitStructure.CAN_AWUM=DISABLE; // Despertar del modo de suspensión a través del software (borrar el bit SLEEP de CAN->MCR) //

CAN_InitStructure.CAN_NART=ENABLE //Deshabilitar la transmisión automática de mensajes //

CAN_InitStructure.CAN_RFLM= DISABLE; //El mensaje no está bloqueado, el nuevo sobrescribe el anterior //

CAN_InitStructure.CAN_TXFP=DISABLE //La prioridad está determinada por el identificador del mensaje //

CAN_InitStructure. CAN_Mode= CAN_Mode_Normal; //Configuración del modo: modo:0, modo normal; 1, modo loopback; //Establecer la velocidad en baudios

CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; / /El ancho del salto de resincronización (Tsjw) es tsjw+1 unidad de tiempo CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq

CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; +1 unidad de tiempo CAN_BS1_1tq ~CAN_BS1_16tq

CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//Tbs2=tbs2+1 unidad de tiempo CAN_BS2_1tq ~ CAN_BS2_8tq

CAN_InitStructure.CAN_Prescaler=9; //El coeficiente de división de frecuencia (Fdiv) es brp+ 1 //

CAN_Init(CAN2, &CAN_InitStructure); // Inicializar CAN2

CAN_FilterInitStructure.CAN_FilterNumber=14; //Filtro 0

CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask

CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32 bits

CAN_FilterInitStructure.CAN_FilterIdHigh=0x0

000;////ID de 32 bits

CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;

CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//MASCARA de 32 bits

CAN_FilterInitStructure .CAN_FilterMaskIdLow =0x0000;

CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0; //El filtro 0 está asociado con FIFO0

CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //Activar el filtro 0

CAN_FilterInit(&CAN_FilterInitStructure);//Inicialización del filtro

#if CAN_RX2_INT_ENABLE

CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE);//Se permite la interrupción del registro de mensajes FIFO0

NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // La prioridad principal es 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 // La prioridad secundaria es 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

#endif

return 0;

}

#if CAN_RX2_INT_ENABLE //Habilitar interrupción RX2

//Función de servicio de interrupción

void CAN2_RX0_IRQHandler(void)

{

CanRxMsg RxMessage;

int i=0;

CAN_Receive(CAN2, 0, &RxMessage);

Can2_Send_Msg(RxMessage.Data,8) ;

}

#endif

//puede enviar un conjunto de datos (formato fijo: ID es 0X12, marco estándar, marco de datos)

//len: longitud de datos (máximo 8)

//msg: puntero de datos, máximo 8 bytes.

//valor de retorno: 0, éxito;

//Otro, fallido;

u8 Can2_Send_Msg(u8* msg,u8 len)

{

u8 mbox;

u16 i=0;

CanTxMsg TxMessage;

TxMessage.StdId=0x12; // El identificador estándar es 0

TxMessage. // Establecer identificador extendido (29 bits)

TxMessage.IDE=0 // Usar identificador extendido

TxMessage.RTR=0; // El tipo de mensaje es trama de datos, una trama es de 8 bits

TxMessage.DLC=len // Envía dos tramas de información

for(i =0; i<8;i++)

TxMessage.Data[i]=msg[i]; // Información del primer cuadro

mbox= CAN_Transmit(CAN2, &TxMessage); /p >

i=0;

while((CAN_TransmitStatus(CAN2, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++ //Espera a que finalice la transmisión

if (i>=0XFFF)return 1;

return 0;

}

//el puerto puede recibir la consulta de datos

// buf: búfer de datos;

//Valor de retorno: 0, no se recibieron datos;

// Otros, longitud de los datos recibidos;

u8 Can2_Receive_Msg(u8 *buf)

{

u32 i;

CanRxMsg RxMessage;

if( CAN_MessagePending(CAN2,CAN_FIFO0) = =0)return 0; //No se recibieron datos, salga directamente

CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);//Leer datos

for(i=0;i < 8;i++)

buf[i]=RxMessage.Data[i];

devuelve RxMessage.DLC

}