ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Среда
10 июля
333788 Топик полностью
Chum_A (07.06.2012 12:55, просмотров: 371) ответил Stepanov.I.L на здравствуйте, интересует следующий вопрос: при попытке выйти из режима инициализиализации кан, в нормальный режим работы бит INRQ (регистр MCR) обнуляю запросом на выход из инициализации, однако связанный с ним бит подтверждения запроса INAK
Вдруг поможет. Без коментариев и обязательств :). Это кусок старого (но рабочего) проекта с творчески доработанным кодом от STM-demo. Тактовая CPU, кажется, 32МГц.  /*---------------------------------------------------------------------------- * Name: Can.c * Purpose: CAN interface for STM32 * Version: V1.01 *---------------------------------------------------------------------------- * This file is part of the uVision/ARM development tools. * This software may only be used under the terms of a valid, current, * end user licence from KEIL for a compatible version of KEIL software * development tools. Nothing else gives you the right to use this software. * * Copyright (c) 2005-2007 Keil Software. All rights reserved. *----------------------------------------------------------------------------*/ #include <stm32f10x_lib.h> // STM32F10x Library Definitions #include "STM32_Reg.h" // STM32 register and bit Definitions #include "STM32_Init.h" // STM32 Initialization #include "Wake.h" #include "CAN.h" // STM32 CAN adaption layer CAN_msg CAN_TxMsg_buf[CAN_STORAGE_BUF_SIZE]; // буфер хранения отправляемых CAN пакетов unsigned char CAN_TxMsg_Head; // индекс пустого слота под сохранение принятого CAN пакета CAN_msg CAN_RxMsg_buf[CAN_STORAGE_BUF_SIZE]; // буфер хранения принятых пакетов unsigned char CAN_RxMsg_Head; // индекс пустого слота под сохранение принятого CAN пакета unsigned char CAN_TxRdy; // CAN HW ready to transmit a message unsigned char CAN_RxOver; // == 1 буфер приемника CAN переполнен, gfrtns yt cj[hfyz.ncz /*---------------------------------------------------------------------------- initialize CAN interface *----------------------------------------------------------------------------*/ void can_Init (void) { CAN_setup(); // setup CAN interface // CAN_wrFilter (33, STANDARD_FORMAT); // Enable reception of messages CAN->FMR |= CAN_FMR_FINIT; // реж. настройки фильтров CAN->FM1R = 0; // традиционный режим ID + MASK CAN->FS1R = 1; // один 32-bit ID (а не два 16-bit ID) CAN->sFilterRegister[0].FR1 = 0; // 32-bit ID CAN->sFilterRegister[0].FR2 = 0; // 32-bit MASK т.е. прием всех ID CAN->FFA1R = 0; // assign filter to FIFO 0 CAN->FA1R = 1; // activate filter CAN->FMR &= ~CAN_FMR_FINIT; // reset Initialisation mode for filter banks /* COMMENT THE LINE BELOW TO ENABLE DEVICE TO PARTICIPATE IN CAN NETWORK */ // CAN_testmode(CAN_BTR_SILM | CAN_BTR_LBKM); // Loopback, Silent Mode (self-test) CAN_start(); // leave init mode CAN_waitReady(); // wait til mbx is empty } /*---------------------------------------------------------------------------- setup CAN interface *----------------------------------------------------------------------------*/ void CAN_setup (void) { RCC->APB1ENR |= RCC_APB1ENR_CANEN; // enable clock for CAN // Note: uses PB8 and PB9 for CAN RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // enable clock for Alternate Function AFIO->MAPR &= 0xFFFF9FFF; // reset CAN remap AFIO->MAPR |= 0x00004000; // set CAN remap, use PB8, PB9 RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // enable clock for GPIO B GPIOB->CRH &= ~(0x0F<<0); GPIOB->CRH |= (0x08<<0); // CAN RX pin PB.8 input push pull GPIOB->CRH &= ~(0x0F<<4); GPIOB->CRH |= (0x0B<<4); // CAN TX pin PB.9 alternate output push pull NVIC->ISER[0] |= (1 << (USB_HP_CAN_TX_IRQChannel & 0x1F)); // enable interrupt NVIC->ISER[0] |= (1 << (USB_LP_CAN_RX0_IRQChannel & 0x1F)); // enable interrupt CAN->MCR = (CAN_MCR_NART | CAN_MCR_INRQ); // init mode, disable auto. retransmission // Note: only FIFO 0, transmit mailbox 0 used CAN->IER = (CAN_IER_FMPIE0 | CAN_IER_TMEIE); // FIFO 0 msg pending, Transmit mbx empty /* Note: this calculations fit for PCLK1 = 32 MHz */ CAN->BTR &= ~((( 0x03) << 24) | (( 0x07) << 20) | (( 0x0F) << 16) | ( 0x1FF)); //#define CAN_125KB /* set BTR register so that sample point is at about 72% bit time from bit start */ /* TSEG1 = 9, TSEG2 = 4, SJW = 3 => 1 CAN bit = 18 TQ, sample at 72% */ // SJW TS2 TS1 Tq #ifdef CAN_125KB CAN->BTR |= ((((4-1) & 0x03) << 24) | (((5-1) & 0x07) << 20) | (((10-1) & 0x0F) << 16) | ((16-1) & 0x1FF)); #else // 500 kbt CAN->BTR |= ((((4-1) & 0x03) << 24) | (((5-1) & 0x07) << 20) | (((10-1) & 0x0F) << 16) | ((4-1) & 0x1FF)); #endif } /*---------------------------------------------------------------------------- leave initialisation mode *----------------------------------------------------------------------------*/ void CAN_start (void) { CAN->MCR &= ~CAN_MCR_INRQ; // normal operating mode, reset INRQ while (CAN->MSR & CAN_MCR_INRQ); } /*---------------------------------------------------------------------------- set the testmode *----------------------------------------------------------------------------*/ void CAN_testmode (unsigned int testmode) { CAN->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM); // set testmode CAN->BTR |= (testmode & (CAN_BTR_SILM | CAN_BTR_LBKM)); } /*---------------------------------------------------------------------------- check if transmit mailbox is empty *----------------------------------------------------------------------------*/ void CAN_waitReady (void) { while ((CAN->TSR & CAN_TSR_TME0) == 0); // Transmit mailbox 0 is empty CAN_TxRdy = 1; } /*---------------------------------------------------------------------------- wite a message to CAN peripheral and transmit it *----------------------------------------------------------------------------*/ void CAN_wrMsg (CAN_msg *msg) { CAN->sTxMailBox[0].TIR = (unsigned int)0; // Reset TIR register // Setup identifier information if (msg->format == STANDARD_FORMAT) { // Standard ID CAN->sTxMailBox[0].TIR |= (unsigned int)(msg->id << 21) | CAN_ID_STD; } else { // Extended ID CAN->sTxMailBox[0].TIR |= (unsigned int)(msg->id << 3) | CAN_ID_EXT; } // Setup type information if (msg->type == DATA_FRAME) { // DATA FRAME CAN->sTxMailBox[0].TIR |= CAN_RTR_DATA; } else { // REMOTE FRAME CAN->sTxMailBox[0].TIR |= CAN_RTR_REMOTE; } // Setup data bytes CAN->sTxMailBox[0].TDLR = (((unsigned int)msg->data[3] << 24) | ((unsigned int)msg->data[2] << 16) | ((unsigned int)msg->data[1] << 8) | ((unsigned int)msg->data[0]) ); CAN->sTxMailBox[0].TDHR = (((unsigned int)msg->data[7] << 24) | ((unsigned int)msg->data[6] << 16) | ((unsigned int)msg->data[5] << 8) | ((unsigned int)msg->data[4]) ); // Setup length CAN->sTxMailBox[0].TDTR &= ~CAN_TDTxR_DLC; CAN->sTxMailBox[0].TDTR |= (msg->len & CAN_TDTxR_DLC); CAN->IER |= CAN_IER_TMEIE; // enable TME interrupt CAN->sTxMailBox[0].TIR |= CAN_TIxR_TXRQ; // transmit message } /*---------------------------------------------------------------------------- read a message from CAN peripheral and release it *----------------------------------------------------------------------------*/ void CAN_rdMsg (CAN_msg *msg) { // Read identifier information if ((CAN->sFIFOMailBox[0].RIR & CAN_ID_EXT) == 0) { // Standard ID msg->format = STANDARD_FORMAT; msg->id = (u32)0x000007FF & (CAN->sFIFOMailBox[0].RIR >> 21); } else { // Extended ID msg->format = EXTENDED_FORMAT; msg->id = (u32)0x0003FFFF & (CAN->sFIFOMailBox[0].RIR >> 3); } // Read type information if ((CAN->sFIFOMailBox[0].RIR & CAN_RTR_REMOTE) == 0) { msg->type = DATA_FRAME; // DATA FRAME } else { msg->type = REMOTE_FRAME; // REMOTE FRAME } // Read length (number of received bytes) msg->len = (unsigned char)0x0000000F & CAN->sFIFOMailBox[0].RDTR; // Read data bytes msg->data[0] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR); msg->data[1] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 8); msg->data[2] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 16); msg->data[3] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 24); msg->data[4] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR); msg->data[5] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 8); msg->data[6] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 16); msg->data[7] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 24); CAN->RF0R |= CAN_RF0R_RFOM0; // Release FIFO 0 output mailbox } void CAN_wrFilter (unsigned int id, unsigned char format) { static unsigned short CAN_filterIdx = 0; unsigned int CAN_msgId = 0; if (CAN_filterIdx > 13) { // check if Filter Memory is full return; } // Setup identifier information if (format == STANDARD_FORMAT) { // Standard ID CAN_msgId |= (unsigned int)(id << 21) | CAN_ID_STD; } else { // Extended ID CAN_msgId |= (unsigned int)(id << 3) | CAN_ID_EXT; } CAN->FMR |= CAN_FMR_FINIT; // set Initialisation mode for filter banks CAN->FA1R &= ~(unsigned int)(1 << CAN_filterIdx); // deactivate filter // initialize filter CAN->FS1R |= (unsigned int)(1 << CAN_filterIdx);// set 32-bit scale configuration CAN->FM1R |= (unsigned int)(1 << CAN_filterIdx);// set 2 32-bit identifier list mode CAN->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId; // 32-bit identifier CAN->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgId; // 32-bit identifier CAN->FFA1R &= ~(unsigned int)(1 << CAN_filterIdx); // assign filter to FIFO 0 CAN->FA1R |= (unsigned int)(1 << CAN_filterIdx); // activate filter CAN->FMR &= ~CAN_FMR_FINIT; // reset Initialisation mode for filter banks CAN_filterIdx += 1; // increase filter index } /*---------------------------------------------------------------------------- CAN transmit interrupt handler *----------------------------------------------------------------------------*/ void __irq USB_HP_CAN_TX_IRQHandler (void) { if (CAN->TSR & CAN_TSR_RQCP0) // request completed mbx 0 { CAN->TSR |= CAN_TSR_RQCP0; // reset request complete mbx 0 CAN->IER &= ~CAN_IER_TMEIE; // disable TME interrupt CAN_TxRdy = 1; } } //---------------------------------------------------------------------------- // CAN receive interrupt handler // при приеме CAN пакета: // если CAN_RxMsg_Head < CAN_STORAGE_BUF_SIZE помещаем его в CAN_RxMsg_buf[] // и ++CAN_RxMsg_Head //---------------------------------------------------------------------------- void __irq USB_LP_CAN_RX0_IRQHandler (void) { if (CAN->RF0R & CAN_RF0R_FMP0) { if(CAN_RxMsg_Head < CAN_STORAGE_BUF_SIZE) // в буфере еще есть место { CAN_rdMsg (&CAN_RxMsg_buf[CAN_RxMsg_Head]); ++CAN_RxMsg_Head; } else CAN_RxOver = 1; } }