Elcarnado 0 6 марта, 2013 Опубликовано 6 марта, 2013 (изменено) · Жалоба Здравствуйте! Начал осваивать 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. Помогите, пожалуйста, разобраться. Изменено 6 марта, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 6 марта, 2013 Опубликовано 6 марта, 2013 · Жалоба Так-с... С этой проблемкой воде разобрался (понадобился незамыленный взгляд другого человека). Вместо RCC_APB2PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); должно быть конечно же RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 6 марта, 2013 Опубликовано 6 марта, 2013 (изменено) · Жалоба Вроде всё у вас нормально. Я правда с 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); Изменено 6 марта, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 6 марта, 2013 Опубликовано 6 марта, 2013 · Жалоба Эх... Кан все-равно не работает ((( Объявляю переменную типа 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); // Отправляем сообщение Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба Здравствуйте! После отправки сообщения проверяю в бесконечном цикле статус сообщения функцией CAN_TransmitStatus. Заметил, что эта функция всегда возвращает статус сообщения как "в ожидании" (CAN_TxStatus_Pending) и сообщение никогда не отправляется. Мне кажется, я что-то упустил при настройке контроллера либо самого CAN. Подскажите пожалуйста, что еще нужно посмотреть... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба вопрос в том есть ли приемники сообщения? если на линии никого нет, то никто не выставит бит что сообщение принято, и оно никогда не отправиться... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба вопрос в том есть ли приемники сообщения? если на линии никого нет, то никто не выставит бит что сообщение принято, и оно никогда не отправиться... А вот об этом я как раз и не подумал... Спасибо! Будет теперь над чем поразмыслить в выходные. Думаю, именно поэтому, когда я выставляю LoopMode (когда TX на RX замыкается), то сообщение вроде бы как отправляется (не уверен по причине того, что осциллографом я так ничего пока и не увидел, но функция CAN_TransmitStatus возвращает значение "отправлено"). А подскажите пожалуйста, необходимо ли на линии два резистора между RX и TX или достаточно будет одного? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба Все зависит. Есть стандарт и рекомендации лучше им следовать. На коротких линиях работает и без резистора. Но лучше делать хорошо, а плохо оно само получится. Учитывайте что очень много чего от вас спрятано железной реализацией кана, проверки контрольных сумм, повторные отправки и так далее.. И если на линии будут сложности в условиях лаборатории вы их сможете и не заметить, а поставив на реальный объект удивитесь. Те кто развивает кан потратили не мало времени на выработку оптимальных рекомендаций и им лучше следовать... кстати в луп моде вроде бы подтверждения отправки не выставляются, но я могу ошибаться, нет описания под рукой. Может внутри процессора выставляются... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 11 марта, 2013 Опубликовано 11 марта, 2013 · Жалоба Доброго вечера! Снова прошу вашей помощи. Интерфейс КАН заработал и на осциллографе даже сигналы видны (сколько радости то было :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. Подскажите пожалуйста, где может быть ошибка? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 марта, 2013 Опубликовано 12 марта, 2013 · Жалоба посмотрите в таблице прерываний CAN1_RX1_IRQn какую функцию вызывает. так вы определитесь с функцией... потом void CAN1_RX1_IRQHandler(void) {...} в зависимости от среды надо проверить иногда требуется обозначить что это функция прерывание. либо прагмой либо еще как... В проекте есть еще хоть какие -то прерывания? вы их так же вызываете? Проверьте регистры КАН, там может быть глобальный флаг на разрешение-запрещение всех прерываний Я бы проверил значение регистров после инициализации, и сравнил с тем что там должно быть по описанию. Библиотеки - это весело и здорово, но их тоже люди пишут, а читать описание как ими пользоваться у нас не в почете... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 13 марта, 2013 Опубликовано 13 марта, 2013 (изменено) · Жалоба посмотрите в таблице прерываний 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: Изменено 13 марта, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 марта, 2013 Опубликовано 13 марта, 2013 · Жалоба startup_stm32f10x_md.c - близко, почти горячо:)... вы нашли описание, прототипы функций. А надо найти вызовы%)... CAN1_SCE_IRQHandler - вот это что за прерывание? доберусь до работы завтра погляжу что там не так Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 13 марта, 2013 Опубликовано 13 марта, 2013 · Жалоба 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. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 13 марта, 2013 Опубликовано 13 марта, 2013 · Жалоба С прерывания более-менее разобрался. Я включал и опрашивал не то прерывание. Для прерывания по приему данных необходимо включать вот этот вектор в NVIC: USB_LP_CAN1_RX0_IRQn Разрешать вот это событие в Can: CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); И вызывать вот этот обработчик: void USB_LP_CAN1_RX0_IRQHandler(void). Теперь другая печаль В обработчике прерывания я в глобальную переменную записываю 1. А в основной программе зажигаю светодиод по этой единичке. Так вот, если программу выполнять пошагово через дебаггер, то в прерывание я попадаю и светодиод благополучно загорается. А если загрузить эту программу на выполнение в реальном времени, то светодиод не загорается. Может, посоветуете чего по этому поводу? Приписать volatile к переменной. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 марта, 2013 Опубликовано 13 марта, 2013 · Жалоба почему USB? volatile - возможно, но почему в дебагере работает? Меняется оптимизация? Ведь если переменная была с оптимизирована в рабочем варианте, то она будет с оптимизирована и в дебагере, и наоборот. Думаю либо прерывание вызывается так часто что вы в обычном режиме не попадаете в нормальный цикл, то есть при выполнении никогда не выходите из функции прерывания... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться