|
Can в STM32F103RBT6 |
|
|
|
Mar 6 2013, 09:24
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Здравствуйте! Начал осваивать stm и интерфейс can, пытаюсь осуществить передачу по данному интерфейсу, но пока тщетно. Для инициализации использую стандартные API-функции в программе CooCox. Заметил такую вещь: регистр MCR, отвечающий за режимы работы Can-интерфейса, не изменяет своего значения: то есть код вида "CANx->MCR = CANx->MCR | 0x0001" никак не влияет на состояние регистра. Пробовал разобраться по примеру, приведенному в CooCox, но еще больше запутался  В этом примере никак не инициализируется порт для CAN, не делается ремаппинг и AFIO и не используется регистр MCR (он нужен для переключения режимов Sleep->Normal->Initialisation). Мой листинг настройки Can: CODE 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 - Mar 6 2013, 20:05
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 6 2013, 12:26
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Так-с... С этой проблемкой воде разобрался (понадобился незамыленный взгляд другого человека). Вместо RCC_APB2PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); должно быть конечно же RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
|
|
|
|
|
Mar 6 2013, 12:55
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Вроде всё у вас нормально. Я правда с 105 работал. Я ещё фильтра настраивал, но вроде это не принципиально CODE /* 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 - Mar 6 2013, 20:05
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 6 2013, 14:27
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Эх... Кан все-равно не работает ((( Объявляю переменную типа 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); // Отправляем сообщение
|
|
|
|
|
Mar 7 2013, 09:14
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

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

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Цитата(Golikov A. @ Mar 7 2013, 14:18)  вопрос в том есть ли приемники сообщения? если на линии никого нет, то никто не выставит бит что сообщение принято, и оно никогда не отправиться... А вот об этом я как раз и не подумал... Спасибо! Будет теперь над чем поразмыслить в выходные. Думаю, именно поэтому, когда я выставляю LoopMode (когда TX на RX замыкается), то сообщение вроде бы как отправляется (не уверен по причине того, что осциллографом я так ничего пока и не увидел, но функция CAN_TransmitStatus возвращает значение "отправлено"). А подскажите пожалуйста, необходимо ли на линии два резистора между RX и TX или достаточно будет одного?
|
|
|
|
|
Mar 11 2013, 15:37
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Доброго вечера! Снова прошу вашей помощи. Интерфейс КАН заработал и на осциллографе даже сигналы видны (сколько радости то было  ). Помогите настроить прерывания по приему сообщения (Интерфейс работает в режиме 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. Подскажите пожалуйста, где может быть ошибка?
|
|
|
|
|
Mar 13 2013, 07:59
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Цитата(Golikov A. @ Mar 12 2013, 19:12)  посмотрите в таблице прерываний CAN1_RX1_IRQn какую функцию вызывает. так вы определитесь с функцией...
потом void CAN1_RX1_IRQHandler(void) {...} в зависимости от среды надо проверить иногда требуется обозначить что это функция прерывание. либо прагмой либо еще как... В проекте есть еще хоть какие -то прерывания? вы их так же вызываете?
Проверьте регистры КАН, там может быть глобальный флаг на разрешение-запрещение всех прерываний
Я бы проверил значение регистров после инициализации, и сравнил с тем что там должно быть по описанию. Библиотеки - это весело и здорово, но их тоже люди пишут, а читать описание как ими пользоваться у нас не в почете... Спасибо за советы! Вопрос от новичка: а где посмотреть таблицу прерываний? Я нашел только список прерываний с номерами в файле stm32f10x.h: CODE 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: CODE 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. Была бы документация на эту библиотеку - с удовольствием почитал бы
Сообщение отредактировал IgorKossak - Mar 13 2013, 17:47
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 13 2013, 15:32
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Цитата(Golikov A. @ Mar 13 2013, 17:01)  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). Теперь другая печаль  В обработчике прерывания я в глобальную переменную записываю 1. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу?
|
|
|
|
|
Mar 13 2013, 16:30
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Elcarnado @ Mar 13 2013, 19:32)  С прерывания более-менее разобрался. Я включал и опрашивал не то прерывание. Для прерывания по приему данных необходимо включать вот этот вектор в NVIC: USB_LP_CAN1_RX0_IRQn Разрешать вот это событие в Can: CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); И вызывать вот этот обработчик: void USB_LP_CAN1_RX0_IRQHandler(void). Теперь другая печаль  В обработчике прерывания я в глобальную переменную записываю 1. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу?  Приписать volatile к переменной.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|