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> 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 p>
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ón
p>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++; p>
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 p>
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 // p>
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
}