Перейти к содержанию
    

Здравствуйте! Начал осваивать stm и интерфейс can, пытаюсь осуществить передачу по данному интерфейсу, но пока тщетно. Для инициализации использую стандартные API-функции в программе CooCox. Заметил такую вещь: регистр MCR, отвечающий за режимы работы Can-интерфейса, не изменяет своего значения: то есть код вида "CANx->MCR = CANx->MCR | 0x0001" никак не влияет на состояние регистра. Пробовал разобраться по примеру, приведенному в CooCox, но еще больше запутался :rolleyes: В этом примере никак не инициализируется порт для CAN, не делается ремаппинг и AFIO и не используется регистр MCR (он нужен для переключения режимов Sleep->Normal->Initialisation).

Мой листинг настройки Can:

void Init_Can(void)
{
// Инициализация порта
RCC_APB2PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);	// включаем тактирование CAN1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 	// включаем тактирование AFIO
GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);		// Переносим Can1 на PB8, PB9
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 	// включаем тактирование порта B

// CAN RX pin PB.8 input push pull
GPIO_InitTypeDef INIT_GPIO_B;				// Объявляем структуру для инициализации порта
GPIO_StructInit(&INIT_GPIO_B);				// заполняем дефолтными значениями
INIT_GPIO_B.GPIO_Mode  = GPIO_Mode_IPU;			// Режим - вход Pull-up (см. RM0041 p.154)
INIT_GPIO_B.GPIO_Pin   = GPIO_Pin_8;			// Настраиваем пин 8 порта B
INIT_GPIO_B.GPIO_Speed = GPIO_Speed_10MHz;		// Скорость изменения пина
GPIO_Init(GPIOC, &INIT_GPIO_B);				// Загрузка структуры настройки

// CAN TX pin PB.9 Alternative function Push-pull
INIT_GPIO_B.GPIO_Mode  = GPIO_Mode_AF_PP;		// Режим - Alternative Push-pull 
INIT_GPIO_B.GPIO_Pin   = GPIO_Pin_9;			// Настраиваем пин 9 порта B
INIT_GPIO_B.GPIO_Speed = GPIO_Speed_10MHz;		// Скорость изменения пина
GPIO_Init(GPIOC, &INIT_GPIO_B);				// Загрузка структуры настройки

//Переход в режим настройки CAN
uint8_t ini = CAN_OperatingModeRequest(CAN1, CAN_OperatingMode_Initialization);
CAN_InitTypeDef CAN1_InitStruct;
CAN_StructInit(&CAN1_InitStruct);
CAN1_InitStruct.CAN_BS1 = CAN_BS1_3tq;
CAN1_InitStruct.CAN_BS2 = CAN_BS2_2tq;
CAN1_InitStruct.CAN_Prescaler = 24;				//250 kbit/s (Prescaler = 6*10^6 / Speed)
CAN_Init(CAN1, &CAN1_InitStruct);

// Переход в нормальный режим работы CAN
uint8_t normal = CAN_OperatingModeRequest(CAN1, CAN_OperatingMode_Normal);

Данный код никак не влияет на состояние CAN-интерфейса и он продолжает спокойно пребывать в режиме SLEEP.

Функция CAN_OperatingModeRequest() взята из файла stm32f10x_can.h.

Помогите, пожалуйста, разобраться.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так-с... С этой проблемкой воде разобрался (понадобился незамыленный взгляд другого человека). Вместо

RCC_APB2PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

должно быть конечно же

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде всё у вас нормально.

Я правда с 105 работал. Я ещё фильтра настраивал, но вроде это не принципиально

 

  /* CAN cell init */
 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_5tq;
 CAN_InitStructure.CAN_Prescaler = 16;					// 250 кбит
 CAN_Init(CAN1, &CAN_InitStructure);

 /* CAN filter 0 init */
 CAN_FilterInitStructure.CAN_FilterNumber=0;
 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
 CAN_FilterInitStructure.CAN_FilterIdHigh= (PCAN_ID_PC1_FLT>>13) & 0xffff;
 CAN_FilterInitStructure.CAN_FilterIdLow=  (PCAN_ID_PC1_FLT<<3)  & 0xffff;
 CAN_FilterInitStructure.CAN_FilterMaskIdHigh=	 (PCAN_ID_PC1_MSK>>13) & 0xffff;
 CAN_FilterInitStructure.CAN_FilterMaskIdLow=  (PCAN_ID_PC1_MSK<<3) & 0xffff;
 CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
 CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
 CAN_FilterInit(&CAN_FilterInitStructure);

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эх... Кан все-равно не работает ((( Объявляю переменную типа CanTxMsg, заполняю её поля и отсылаю командой CanTransmit(). На пинах порта после выполнения команды висит +3v и никаких телодвижений.... Вот код инициализации и отправки сообщения:

        CanTxMsg msg;                         // Объявляем переменную для отправки
    msg.StdId = 0x00;                    // Стандартный ID сообщения
    msg.ExtId = 0x1234;                 // Расширенный ID сообщения
    msg.IDE = CAN_ID_EXT;           // Использовать расширенный ID
    msg.RTR = CAN_RTR_DATA;     // Уже забыл что это, но мне сейчас наполнение фрейма вообще не важно
    msg.DLC = 2;                            // Отправляем 2 байта
    msg.Data[0] = 0xDE;                  // байт 1 
    msg.Data[1] = 0xCA;                 // байт 2 

    uint8_t TR = CAN_Transmit(CAN1, &msg); // Отправляем сообщение

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте! После отправки сообщения проверяю в бесконечном цикле статус сообщения функцией CAN_TransmitStatus. Заметил, что эта функция всегда возвращает статус сообщения как "в ожидании" (CAN_TxStatus_Pending) и сообщение никогда не отправляется. Мне кажется, я что-то упустил при настройке контроллера либо самого CAN. Подскажите пожалуйста, что еще нужно посмотреть...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вопрос в том есть ли приемники сообщения? если на линии никого нет, то никто не выставит бит что сообщение принято, и оно никогда не отправиться...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вопрос в том есть ли приемники сообщения? если на линии никого нет, то никто не выставит бит что сообщение принято, и оно никогда не отправиться...

А вот об этом я как раз и не подумал... Спасибо! Будет теперь над чем поразмыслить в выходные. Думаю, именно поэтому, когда я выставляю LoopMode (когда TX на RX замыкается), то сообщение вроде бы как отправляется (не уверен по причине того, что осциллографом я так ничего пока и не увидел, но функция CAN_TransmitStatus возвращает значение "отправлено").

А подскажите пожалуйста, необходимо ли на линии два резистора между RX и TX или достаточно будет одного?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все зависит. Есть стандарт и рекомендации лучше им следовать. На коротких линиях работает и без резистора. Но лучше делать хорошо, а плохо оно само получится. Учитывайте что очень много чего от вас спрятано железной реализацией кана, проверки контрольных сумм, повторные отправки и так далее.. И если на линии будут сложности в условиях лаборатории вы их сможете и не заметить, а поставив на реальный объект удивитесь. Те кто развивает кан потратили не мало времени на выработку оптимальных рекомендаций и им лучше следовать...

 

кстати в луп моде вроде бы подтверждения отправки не выставляются, но я могу ошибаться, нет описания под рукой. Может внутри процессора выставляются...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго вечера! Снова прошу вашей помощи. Интерфейс КАН заработал и на осциллографе даже сигналы видны (сколько радости то было :rolleyes: ). Помогите настроить прерывания по приему сообщения (Интерфейс работает в режиме LoopMode, - хочу получить прерывание от своих же пакетов). Вот как я настраиваю NVIC:

void Init_NVIC(void)
    {
    __enable_irq ();                                //Разрешить глобальные прерывания

    NVIC_InitTypeDef nvic;
    nvic.NVIC_IRQChannel =  CAN1_RX1_IRQn;            //Прерывание по получению сообщения
    nvic.NVIC_IRQChannelCmd = ENABLE;
    nvic.NVIC_IRQChannelPreemptionPriority = 1;
    nvic.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&nvic);                                //Инициализация контроллера прерываний

    CAN_ITConfig(CAN1,CAN_IT_TME| CAN_IT_FMP0|CAN_IT_FMP1,ENABLE); // Настройка event для КАН-интерфейса.

Пробовал также включать прерывания по SLEEP и WAKE UP, но тщетно. Меня терзают смутные сомнения насчет правильности имени обработчика прерывания, у меня обработка происходит в функции с именем

void CAN1_RX1_IRQHandler(void) {...}

Имя функции взял из файла startup_stm32f10x_md. Подскажите пожалуйста, где может быть ошибка?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

посмотрите в таблице прерываний

CAN1_RX1_IRQn

какую функцию вызывает.

так вы определитесь с функцией...

 

потом

void CAN1_RX1_IRQHandler(void) {...}

в зависимости от среды надо проверить иногда требуется обозначить что это функция прерывание. либо прагмой либо еще как... В проекте есть еще хоть какие -то прерывания? вы их так же вызываете?

 

Проверьте регистры КАН, там может быть глобальный флаг на разрешение-запрещение всех прерываний

 

Я бы проверил значение регистров после инициализации, и сравнил с тем что там должно быть по описанию. Библиотеки - это весело и здорово, но их тоже люди пишут, а читать описание как ими пользоваться у нас не в почете...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

посмотрите в таблице прерываний

CAN1_RX1_IRQn

какую функцию вызывает.

так вы определитесь с функцией...

 

потом

void CAN1_RX1_IRQHandler(void) {...}

в зависимости от среды надо проверить иногда требуется обозначить что это функция прерывание. либо прагмой либо еще как... В проекте есть еще хоть какие -то прерывания? вы их так же вызываете?

 

Проверьте регистры КАН, там может быть глобальный флаг на разрешение-запрещение всех прерываний

 

Я бы проверил значение регистров после инициализации, и сравнил с тем что там должно быть по описанию. Библиотеки - это весело и здорово, но их тоже люди пишут, а читать описание как ими пользоваться у нас не в почете...

 

Спасибо за советы! Вопрос от новичка: а где посмотреть таблицу прерываний? Я нашел только список прерываний с номерами в файле stm32f10x.h:

ADC1_2_IRQn				 = 18,	 /*!< ADC1 and ADC2 global Interrupt	*/
 USB_HP_CAN1_TX_IRQn		 = 19,	 /*!< USB Device High Priority or CAN1 TX Interrupts	*/
 USB_LP_CAN1_RX0_IRQn		= 20,	 /*!< USB Device Low Priority or CAN1 RX0 Interrupts	*/
 CAN1_RX1_IRQn			   = 21,	 /*!< CAN1 RX1 Interrupt				*/
 CAN1_SCE_IRQn			   = 22,	 /*!< CAN1 SCE Interrupt				*/
 EXTI9_5_IRQn				= 23,	 /*!< External Line[9:5] Interrupts		*/
 TIM1_BRK_IRQn			   = 24,	 /*!< TIM1 Break Interrupt				*/
 TIM1_UP_IRQn				= 25,	 /*!< TIM1 Update Interrupt			*/
 TIM1_TRG_COM_IRQn		   = 26,	 /*!< TIM1 Trigger and Commutation Interrupt		*/
 TIM1_CC_IRQn				= 27,	 /*!< TIM1 Capture Compare Interrupt		*/
 TIM2_IRQn				   = 28,	 /*!< TIM2 global Interrupt			*/
 TIM3_IRQn				   = 29,	 /*!< TIM3 global Interrupt			*/
 TIM4_IRQn				   = 30,	 /*!< TIM4 global Interrupt			*/
 I2C1_EV_IRQn				= 31,	 /*!< I2C1 Event Interrupt			*/
 I2C1_ER_IRQn				= 32,	 /*!< I2C1 Error Interrupt			*/
 I2C2_EV_IRQn				= 33,	 /*!< I2C2 Event Interrupt			*/
 I2C2_ER_IRQn				= 34,	 /*!< I2C2 Error Interrupt			*/
 SPI1_IRQn				   = 35,	 /*!< SPI1 global Interrupt			*/
 SPI2_IRQn				   = 36,	 /*!< SPI2 global Interrupt			*/
 USART1_IRQn				 = 37,	 /*!< USART1 global Interrupt			*/
 USART2_IRQn				 = 38,	 /*!< USART2 global Interrupt			*/
 USART3_IRQn				 = 39,	 /*!< USART3 global Interrupt			*/
 EXTI15_10_IRQn			  = 40,	 /*!< External Line[15:10] Interrupts			*/
 RTCAlarm_IRQn			   = 41,	 /*!< RTC Alarm through EXTI Line Interrupt		*/
 USBWakeUp_IRQn			  = 42	  /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */

и список обработчиков прерываний в файле startup_stm32f10x_md.c:

 

void WEAK  Reset_Handler(void);
void WEAK  NMI_Handler(void);
void WEAK  HardFault_Handler(void);
void WEAK  MemManage_Handler(void);
void WEAK  BusFault_Handler(void);
void WEAK  UsageFault_Handler(void);
void WEAK  SVC_Handler(void);
void WEAK  DebugMon_Handler(void);
void WEAK  PendSV_Handler(void);
void WEAK  SysTick_Handler(void);
void WEAK  WWDG_IRQHandler(void);
void WEAK  PVD_IRQHandler(void);
void WEAK  TAMPER_IRQHandler(void);
void WEAK  RTC_IRQHandler(void);
void WEAK  FLASH_IRQHandler(void);
void WEAK  RCC_IRQHandler(void);
void WEAK  EXTI0_IRQHandler(void);
void WEAK  EXTI1_IRQHandler(void);
void WEAK  EXTI2_IRQHandler(void);
void WEAK  EXTI3_IRQHandler(void);
void WEAK  EXTI4_IRQHandler(void);
void WEAK  DMA1_Channel1_IRQHandler(void);
void WEAK  DMA1_Channel2_IRQHandler(void);
void WEAK  DMA1_Channel3_IRQHandler(void);
void WEAK  DMA1_Channel4_IRQHandler(void);
void WEAK  DMA1_Channel5_IRQHandler(void);
void WEAK  DMA1_Channel6_IRQHandler(void);
void WEAK  DMA1_Channel7_IRQHandler(void);
void WEAK  ADC1_2_IRQHandler(void);
void WEAK  USB_HP_CAN1_TX_IRQHandler(void);
void WEAK  USB_LP_CAN1_RX0_IRQHandler(void);
void WEAK  CAN1_RX1_IRQHandler(void);
void WEAK  CAN1_SCE_IRQHandler(void);
void WEAK  EXTI9_5_IRQHandler(void);
void WEAK  TIM1_BRK_IRQHandler(void);
void WEAK  TIM1_UP_IRQHandler(void);
void WEAK  TIM1_TRG_COM_IRQHandler(void);
void WEAK  TIM1_CC_IRQHandler(void);
void WEAK  TIM2_IRQHandler(void);
void WEAK  TIM3_IRQHandler(void);
void WEAK  TIM4_IRQHandler(void);
void WEAK  I2C1_EV_IRQHandler(void);
void WEAK  I2C1_ER_IRQHandler(void);
void WEAK  I2C2_EV_IRQHandler(void);
void WEAK  I2C2_ER_IRQHandler(void);
void WEAK  SPI1_IRQHandler(void);
void WEAK  SPI2_IRQHandler(void);
void WEAK  USART1_IRQHandler(void);
void WEAK  USART2_IRQHandler(void);
void WEAK  USART3_IRQHandler(void);
void WEAK  EXTI15_10_IRQHandler(void);
void WEAK  RTCAlarm_IRQHandler(void);
void WEAK  USBWakeUp_IRQHandler(void);

 

Чисто теоретически можно догадаться, что к чему, но вот где посмотреть, кто кого вызывает - не могу понять...

P.S. Была бы документация на эту библиотеку - с удовольствием почитал бы :laughing:

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

startup_stm32f10x_md.c - близко, почти горячо:)...

 

 

 

вы нашли описание, прототипы функций. А надо найти вызовы%)...

CAN1_SCE_IRQHandler - вот это что за прерывание?

 

доберусь до работы завтра погляжу что там не так

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

startup_stm32f10x_md.c - близко, почти горячо:)...

 

 

 

вы нашли описание, прототипы функций. А надо найти вызовы%)...

CAN1_SCE_IRQHandler - вот это что за прерывание?

 

доберусь до работы завтра погляжу что там не так

 

С прерывания более-менее разобрался. Я включал и опрашивал не то прерывание. Для прерывания по приему данных необходимо включать вот этот вектор в NVIC:

USB_LP_CAN1_RX0_IRQn

Разрешать вот это событие в Can:

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

И вызывать вот этот обработчик:

void USB_LP_CAN1_RX0_IRQHandler(void).

 

Теперь другая печаль :wacko: В обработчике прерывания я в глобальную переменную записываю 1. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу? :help:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С прерывания более-менее разобрался. Я включал и опрашивал не то прерывание. Для прерывания по приему данных необходимо включать вот этот вектор в NVIC:

USB_LP_CAN1_RX0_IRQn

Разрешать вот это событие в Can:

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

И вызывать вот этот обработчик:

void USB_LP_CAN1_RX0_IRQHandler(void).

 

Теперь другая печаль :wacko: В обработчике прерывания я в глобальную переменную записываю 1. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу? :help:

Приписать volatile к переменной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

почему USB?

 

volatile - возможно, но почему в дебагере работает? Меняется оптимизация? Ведь если переменная была с оптимизирована в рабочем варианте, то она будет с оптимизирована и в дебагере, и наоборот. Думаю либо прерывание вызывается так часто что вы в обычном режиме не попадаете в нормальный цикл, то есть при выполнении никогда не выходите из функции прерывания...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...