Search the Community

Showing results for tags 'прерывания'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Вопрос-Ответ. Для начинающих
    • Песочница (Q&A)
    • Дайте схему!
    • Школьникам и студентам
    • Начинающим
    • Паяльник TV
    • Обсуждение материалов с сайта
  • Радиоэлектроника для профессионалов
    • Световые эффекты и LED
    • Роботы и модели на ДУ-управлении
    • Автоматика
    • Самодельные устройства к компьютеру
    • Программное обеспечение
    • Автомобильная электроника
    • Системы охраны и наблюдения. Личная безопасность
    • Питание
    • Электрика
    • Промышленная электроника
    • Ремонт
    • Металлоискатели
    • Измерительная техника
    • Мастерская радиолюбителя
    • Сотовая связь
    • Спутниковое ТВ
    • КВ и УКВ радиосвязь
    • Жучки
    • Телефония и фрикинг
    • Высокое напряжение
    • Идеи и технологии будущего
    • Справочная радиоэлементов
    • Литература
    • Разное
  • Аудио
    • FAQ, Технологии и компоненты
    • Для начинающих
    • Источники звука
    • Предусилители, темброблоки, фильтры
    • Питание аудио аппаратуры
    • Усилители мощности
    • Акустические системы
    • Авто-аудио
    • Ламповая техника
    • Гитарное оборудование
    • Прочее
  • Микроконтроллеры
    • МК для начинающих
    • AVR
    • PIC
    • STM32
    • Arduino и Raspberry Pi
    • ПЛИС
    • Другие микроконтроллеры и семейства
    • Алгоритмы
    • Программаторы и отладочные модули
    • Периферия и внешние устройства
    • Разное
  • Товары и услуги
    • Коммерческие предложения
    • Продам-Отдам, Услуги
    • Куплю
    • Уголок потребителя
    • Вакансии и разовая работа
    • Наши обзоры и тесты
  • Разное
    • Конкурсы сайта с призами
    • Сайт Паяльник и форум
    • Курилка
    • Технический английский (English)
    • Наши проекты для Android и Web
    • FAQ (Архив)
    • Личные блоги
    • Корзина
    • Вопросы с VK
  • Переделки's ATX->ЛБП
  • Киловольты юмора's Юмор в youtube
  • Радиолюбительская доска объявлений exDIY's Надежность и группы продавцов
  • Переделки's разные темы

Blogs

There are no results to display.

There are no results to display.

Marker Groups

  • Пользователи форума

Город


Сфера радиоэлектроники


Оборудование

Found 22 results

  1. Не могу настроить таймер 0 на работу, и даже не получается понять в чем проблема. Делаю в Proteus, так как это быстрее и нагляднее. Пробовал и просто по переполнению делать прерывание (WGM[1..0] 00) и по совпадению (WGM[1..0] 10; OCR0A = 0 - 255), однако прерываний нет. Перед циклом ставлю TCNT0 = 0; Тактирование выставляю TCCR0B (CS[2..0] 001, 100, 101). Прерывания TIMSK0 (OCIE0A, TOIE0) выставляю, не вызываются. Даже принудительным заносом значения в регистр TIFR0 (OCF0A, TOV0). Прерывание пытаюсь выполнить таким образом: #include <avr/interrupt.h> volatile unsigned int A = 0; ISR(TIMER0_OVF_vect) { A = 1; } ... while(1) { if (A == 1) PORTB |= (1<<0); } Proteus показывает, что вывод настроен как выход, но всегда 0; Конкретный код привести не могу, так как у меня не заработало совсем ничего. Внизу я сделал вырезку из даташита на ATMEGA328 по 0 таймеру 8-бит, и занес в один PDF файл. ATmega328-106-112.pdf Прошу помочь разобраться с таймером и прерываниями для него.
  2. Всем светлым и умным головам привет! Никак не могу найти информацию о данном прерывании TIM1_BRK_UP_TRG_COM. Вопрос 1: Что это за стек или система прерываний? Вопрос 2: Когда будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler, если также есть обработчик прерывания TIM1_CC_IRQHandler? Вопрос 3: период переполнения таймера равен 100 мкс. Сколько раз будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler до обработчика прерывания TIM1_CC_IRQHandler? По логике вещей, предполагаю, что 100 раз? Заранее благодарен! Всем радости))
  3. Всем привет. Столкнулся с такой проблемой: Пишу программу для устройства мониторинга оборотов двух валов используя датчик холла. Настроил прерывания, перевод в RPM, все проверил, в .порт отправляются верные значения, и после настройки индикации столкнулся с проблемой неадекватного поведения переменных считающих millis, а после и индикации. В Arduino я не спец, Гляньте на код, может чем помогите. Заранее благодарен. #include <EEPROM.h> #define CLOCK 13 //SH_CP #define DATA 11 //DS #define LATCH 10 //ST_CP int numbers[5]; boolean ee = 0; int mh; int hh; int et_mah; int et_shl; int ot_mah; int ot_shl; volatile int rpm_mah = 0; volatile int rpm_shl = 0; int rpmmah_count = 0; int rpmshl_count = 0; unsigned long lastmillis_mah = 0; unsigned long lastmillis_shl = 0; unsigned long lastmillis_show = 0; unsigned char number[] = { 0b01111110, //0 0b00110000, //1 0b01101101, //2 0b01111001, //3 0b00110011, //4 0b01011011, //5 0b01011111, //6 0b01110000, //7 0b01111111, //8 0b01111011, //9 0b00000001, //- 0b00000000 //тушим индикатор }; void setup() { Serial.begin(9600); attachInterrupt(0, rpm_mahovik, FALLING); attachInterrupt(1, rpm_shluz, FALLING); pinMode(CLOCK, OUTPUT); pinMode(DATA, OUTPUT); pinMode(LATCH, OUTPUT); } void rpm_mahovik() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/ rpmmah_count++; } void rpm_shluz() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/ rpmshl_count++; } // чтение //int EEPROM_int_read(int addr) { // byte raw[2]; // for (byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr + i); // int &num = (int&)raw; // return num; //} // запись //void EEPROM_int_write(int addr, int num) { // byte raw[2]; // (int&)raw = num; // for (byte i = 0; i < 2; i++) EEPROM.write(addr + i, raw[i]); //} void show () { int x; for (x = 5; x >= 0; x--) { Serial.print("x= "); Serial.println(x); //включаем LATCH (Начинаем общение) digitalWrite(LATCH, LOW); shiftOut(DATA, CLOCK, LSBFIRST, number[numbers[x]]); //выключаем LATCH digitalWrite(LATCH, HIGH); //отключаем LATCH (чтобы регистр не ждал данных) digitalWrite(LATCH, HIGH); } } //void ee_write () { // EEPROM_int_write(0, mh); // EEPROM_int_write(2, hh); // EEPROM_int_write(4, et_mah); // EEPROM_int_write(6, et_shl); // EEPROM_int_write(8, ot_mah); // EEPROM_int_write(10, ot_shl); //} void loop() { // if ((millis() <= 100) & (ee == 0)) { // mh = EEPROM_int_read(0); // hh = EEPROM_int_read(2); // et_mah = EEPROM_int_read(4); // et_shl = EEPROM_int_read(6); // ot_mah = EEPROM_int_read(8); // ot_shl = EEPROM_int_read(10); // ee = 1; // } if (millis() - lastmillis_mah == 1000) { detachInterrupt(0); rpm_mah = rpmmah_count * 60; rpmmah_count = 0; lastmillis_mah = millis(); attachInterrupt(0, rpm_mahovik, FALLING); } if (millis() - lastmillis_shl == 5000) { detachInterrupt(1); rpm_shl = rpmshl_count * 12; rpmshl_count = 0; lastmillis_shl = millis(); attachInterrupt(1, rpm_shluz, FALLING); } if (millis() - lastmillis_show == 1000) { numbers[0] = rpm_mah / 1000; numbers[1] = (rpm_mah % 1000) / 100; numbers[2] = ((rpm_mah % 1000) % 100) / 10; numbers[3] = ((rpm_mah % 1000) % 100) % 10; numbers[4] = rpm_shl / 10; numbers[5] = rpm_shl % 10; lastmillis_show = millis(); show(); Serial.print("RPM mah= "); Serial.println (rpm_mah); Serial.print("RPM shl= "); Serial.println (rpm_shl); Serial.print("Show millis= "); Serial.println(lastmillis_show); Serial.print("Show mah= "); Serial.println(lastmillis_mah); Serial.print("Show shl= "); Serial.println(lastmillis_shl); } }
  4. Добрый день. Пытаюсь сделать прерывания по изменению GP0. Ставлю GP0 на вход, разрешаю прерывания по изменению GPIO, разрешаю глобальные прерывания, ставлю бит IOC0 в 1. Но при изменении GP0 прерывание не срабатывает. Прерывание по переполнению таймера срабатывает отлично. Что я делаю не так? Прикладываю код программы. Если этого недостаточно, чтобы понять проблему, приложил полный код программы файлом. list p=12f683 #include "p12f683.inc" __config 0x3FF4 W_TEMP EQU 0x40 STATUS_TEMP EQU 0x41 flag EQU 0x42 org 0 goto start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x04 MOVWF W_TEMP SWAPF STATUS,W MOVWF STATUS_TEMP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;программа обработки прерываний ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W retfie ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start clrf GPIO movlw 0x07 movwf CMCON0 bsf STATUS,RP0 ;1 bank movlw b'00001001' movwf TRISIO movlw b'10000001' movwf OPTION_REG bcf INTCON,T0IF bsf INTCON,T0IE movf GPIO,w bcf INTCON,GPIF bsf INTCON,GPIE bsf INTCON,GIE movlw b'00000001' movwf IOC bcf STATUS,RP0 ;0 bank movlw .0 movwf TMR0 ask btfss flag,4 ;данный бит устанавливается в программе обработки прерываний goto ask bcf flag,4 call indicate ;подпрограмма indicate выводит значение, полученное в результате ;обработки прерывания, на индикаторы goto ask reciever1.asm
  5. Добавил Модбас в проект все работало. Добавил еще несколько функций в main и модбас перестал работать. Когда присоединяю сериальный кабель модбас IAR дебагер пререстает работать (вероятно есть общие линии). Вопросы : 1. как решить конфликт кабелей (IAR JTAG) и Modbus и отлаживать модбас с его кабелем ? 2. Если решить конфликт кабелей нельзя тогда ... Как симулировать прерывания на ногах UART (модбас) чтобы программа зашла в обработчит прерывания модбас ?
  6. Доброго времени суток. Решил пробудить свои скилы по написанию программ под stm32f103. Поигрался с SMT32CUDEMX и HAL, но вернулся к SLP библиотеке. Начал постепенно наращивать программу по примерам, начиная с GPIO, тактирования и на работе c USART встал. Суть в том что передача по UART идет нормально, а вот прием приводит к "зависанию". Устанавливая бесконечные while с мигалками внутри, я выяснил что по все видимости МК не переходит в прерывания USART1_IRQHandler. Я не могу понять в чем ошибка, раньше с таким не сталкивался, хотя написал несколько программ для stm32f100 .____. Среда разработки Atollic TrusStudio 9.0.0. #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "stm32f10x_usart.h" #include "misc.h" #include <string.h> // тактовый светодиод для индикации #define LED GPIO_Pin_5 #define RX_BUF_SIZE 80 volatile char RX_FLAG_END_LINE = 0; volatile char RXi; volatile char RXc; volatile char RX_BUF[RX_BUF_SIZE] = {'\0'}; volatile char buffer[80] = {'\0'}; void init_GPIO(void); void SetSysClockTo72(void); void init_uart(void); void clear_RXBuffer(void); void USARTSend(const char *pucBuffer); void USART1_IRQHandler(void) { GPIO_ResetBits(GPIOA, LED); //GPIOA->ODR ^= LED; //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { //if ((USART1->SR & USART_FLAG_RXNE) != RESET) { //if ((USART1->SR & USART_SR_RXNE) != (u16)RESET) { if (USART1->SR & USART_SR_RXNE) { // Сбрасываем флаг прерывания USART1->SR &=~ USART_SR_RXNE; //RXc = USART_ReceiveData(USART1); //RX_BUF[RXi] = RXc; //RXi++; //if (RXc != 13) { // if (RXi > RX_BUF_SIZE-1) { // clear_RXBuffer(); // } //} //else { // RX_FLAG_END_LINE = 1; //} //Echo //USARTSend("Interrapt_UART1\r\n"); //USART_SendData(USART1, RXc); } //return } int main(void) { int i; //SetSysClockTo72(); init_GPIO(); init_uart(); USARTSend("Test USART1\r\n"); while (1) { //if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) != 0) { /* Toggle LED which connected to PC13*/ GPIOA->ODR ^= LED; // Invert C13 /* delay */ for(i=0;i<0x100000;i++); /* Toggle LED which connected to PC13*/ GPIOA->ODR ^= LED; /* delay */ for(i=0;i<0x100000;i++); USARTSend("Test USART1\r\n"); //} //else { //GPIO_SetBits(GPIOA, LED); //} } } void init_GPIO(void) { // Создаем класс для постепенной настройки параметров и единовременного применени¤ GPIO_InitTypeDef GPIO_InitStructure; //Настрайваем светодиод, включаем тактирование GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Конфигурация для светодиода, режим работы, максимальная скорость GPIO_InitStructure.GPIO_Pin = LED; // GPIO_Mode_Out_OD выход с открытым стоком, GPIO_Mode_Out_PP выход двумя состояниями // GPIO_Mode_AF_OD выход с открытым стоком для альтернативных функций, GPIO_Mode_AF_PP то же самое, но с двумя состояниями GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Устанавливаем начальное значение SetBits -> High level ("1"), ResetBits -> Low level ("0") GPIO_ResetBits(GPIOA, LED); // Настрайваем пин 9, регистра B на вход, для отладки, включаем тактирование регистра B RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Настрайваем для кнопку, пин, режим, максимальная частота входного сигнала GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // GPIO_Mode_AIN аналоговый вход, GPIO_Mode_IN_FLOATING вход без подтяжки, болтающийся // GPIO_Mode_IPD вход с подтяжкой к земле, GPIO_Mode_IPU вход с подтяжкой к питанию GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void SetSysClockTo72(void) { ErrorStatus HSEStartUpStatus; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/ /* Системный RESET RCC (делать не обязательно, но полезно на этапе отладки) */ RCC_DeInit(); /* Включаем HSE (внешний кварц) */ RCC_HSEConfig( RCC_HSE_ON); /* Ждем пока HSE будет готов */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Если с HSE все в порядке */ if (HSEStartUpStatus == SUCCESS) { /* HCLK = SYSCLK */ /* Смотри на схеме AHB Prescaler. Частота не делится (RCC_SYSCLK_Div1) */ RCC_HCLKConfig( RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ /* Смотри на схеме APB2 Prescaler. Частота не делится (RCC_HCLK_Div1) */ RCC_PCLK2Config( RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ /* Смотри на схеме APB1 Prescaler. Частота делится на 2 (RCC_HCLK_Div2) потому что на выходе APB1 должно быть не более 36МГц (смотри схему) */ RCC_PCLK1Config( RCC_HCLK_Div2); /* PLLCLK = 8MHz * 9 = 72 MHz */ /* Указываем PLL от куда брать частоту (RCC_PLLSource_HSE_Div1) и на сколько ее умножать (RCC_PLLMul_9) */ /* PLL может брать частоту с кварца как есть (RCC_PLLSource_HSE_Div1) или поделенную на 2 (RCC_PLLSource_HSE_Div2). Смотри схему */ //RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); RCC_PLLConfig(0x00010000, RCC_PLLMul_9); /* Включаем PLL */ RCC_PLLCmd( ENABLE); /* Ждем пока PLL будет готов */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } /* Переключаем системное тактирование на PLL */ RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); /* Ждем пока переключиться */ while (RCC_GetSYSCLKSource() != 0x08) { } } else { /* Проблемы с HSE. Тут можно написать свой код, если надо что-то делать когда микроконтроллер не смог перейти на работу с внешним кварцом */ /* Пока тут заглушка - вечный цикл*/ // while (1) { //} } } void init_uart(void) { /* Enable USART1 and GPIOA clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE); /* Configure the GPIOs */ GPIO_InitTypeDef GPIO_InitStructure; /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure the USART1 */ USART_InitTypeDef USART_InitStructure; /* USART1 configuration ------------------------------------------------------*/ /* USART1 configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled - USART Clock disabled - USART CPOL: Clock is active low - USART CPHA: Data is captured on the middle - USART LastBit: The clock pulse of the last data bit is not output to the SCLK pin */ USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); /* Enable USART1 */ USART_Cmd(USART1, ENABLE); /* Enable the USART1 Receive interrupt: this interrupt is generated when the USART1 receive data register is not empty */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* NVIC Configuration */ NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //NVIC_EnableIRQ(USART1_IRQn); } void clear_RXBuffer(void) { for (RXi=0; RXi<RX_BUF_SIZE; RXi++) RX_BUF[RXi] = '\0'; RXi = 0; } void USARTSend(const char *pucBuffer) { while (*pucBuffer) { USART_SendData(USART1, *pucBuffer++); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { } } }
  7. Господа, имею следующий код (а он имеет меня), который вообще никак не заметен микроконтроллером (stm32f103rb, stm32f103c8). Подавая сигналы "0" или "1" на входы прерывания не выполняются. Пробовал вызывать внутреннее прерывание, но попытки были бессмысленны. Что здесь не так? void NVIC_InputInit(void) { RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPCEN; // Тактирование альтернативных функций и порта PIO_INIT_PIN(GPIOC,6,Input_Floating); // PС6,7 на вход PIO_INIT_PIN(GPIOC,7,Input_Floating); PIO_INIT_PIN(GPIOC,10,Output2_Push_Pull); // PС10,11 на выход PIO_INIT_PIN(GPIOC,11,Output2_Push_Pull); AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI6_PC | AFIO_EXTICR2_EXTI7_PC; // Настройка порта и выбор пинов для прерывания EXTI->IMR |= EXTI_IMR_MR6 | EXTI_IMR_MR7; // Разрешаем генерацию прерывания в периферии EXTI->RTSR |= EXTI_RTSR_TR6 | EXTI_RTSR_TR7; // Настроим прерывание на детектирование обоих фронтов EXTI->FTSR |= EXTI_FTSR_TR6 | EXTI_FTSR_TR7; // у двух входов //EXTI->EMR |= EXTI_EMR_MR6; //Разрешение возобновления при внешних событиях // Разрешаем прерывания //uint32_t prioritygroup = NVIC_GetPriorityGrouping(); //uint32_t priority = NVIC_EncodePriority(prioritygroup, 1, 0 ); //NVIC_SetPriority(EXTI9_5_IRQn, priority); NVIC_EnableIRQ(EXTI9_5_IRQn); // Разрешаем глобальные прерывания __enable_irq(); //EXTI->SWIER |= EXTI_IMR_MR7; // Внутреннее прерывание } void EXTI9_5_IRQHandler(void) { if (EXTI->PR & (1<<6)) //проверяем прерывание от EXTI6 { EXTI->PR |= (1<<6); //EXTI->PR |= EXTI_PR_PR6; //сброс флага прерывания PIO_RESET(GPIOC,11); } // if ((EXTI->PR & EXTI_PR_PR7) == EXTI_PR_PR7) if (EXTI->PR & (1<<7)) //проверяем прерывание от EXTI6 { EXTI->PR |= (1<<7); //EXTI->PR |= EXTI_PR_PR7; //сброс флага прерывания PIO_RESET(GPIOC,10); } }
  8. stm32f103c8t6_прерывания

    Доброго! Контроллер stm32f103c8t6. Пишу настройку таймера и его прерываний, но программа зависает через несколько тиков после выхода из самой функции настройки. По коду: в главной функции пишу сразу настройку таймера и далее бесконечный цикл, до которого дело не доходит. На рисунках скрины отладки в момент зависания. void TIM_ini(void) { TIM_TimeBaseInitTypeDef UserTimStruct; NVIC_InitTypeDef UserNVIC_Structure; TIM_DeInit(TIM3); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); UserTimStruct.TIM_ClockDivision = TIM_CKD_DIV4; UserTimStruct.TIM_CounterMode = TIM_CounterMode_Up; UserTimStruct.TIM_Period = 200; UserTimStruct.TIM_Prescaler = 700-1; TIM_TimeBaseInit(TIM3, &UserTimStruct); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); UserNVIC_Structure.NVIC_IRQChannel = TIM3_IRQn; UserNVIC_Structure.NVIC_IRQChannelCmd = ENABLE; UserNVIC_Structure.NVIC_IRQChannelPreemptionPriority = 1; UserNVIC_Structure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&UserNVIC_Structure); } ,
  9. Я верно понимаю, что вектор для прерывания по достижению счетчиком PWM значения TOP совпадает с вектором для переполнения этого же счетчика?
  10. Здравствуйте. Прошу помощи в теме статитическая индикация 6 разрядного 7ми сегментного индикатора по 2м проводам Data и Clock. Есть такой код для 3х разрядного индикатора в CVavr Си Хочу закидывать данные в каждый разряд отдельно, и выводить эти функции в прерываниях avr микроконтроллера. // cd4094 control example by kalobyte.com 2009 #include <avr/io.h> #define F_CPU 1000000UL #include <util/delay.h> #define REG_PORT PORTB #define REG_DDR DDRB #define REG_PIN_DATA 3 #define REG_PIN_CLK 4 //--- #define REG_DATA_ON REG_PORT|=1<<REG_PIN_DATA; #define REG_DATA_OFF REG_PORT&=~(1<<REG_PIN_DATA); #define REG_CLK {REG_PORT|=1<<REG_PIN_CLK;REG_PORT&=~(1<<REG_PIN_CLK);} unsigned char digs[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // katode // unsigned char digs[10]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; //anode void cd4094_init(void){ char i=0; while(i!=24){ REG_CLK i++; } } void cd4094(int dig){ char i,tmp,j; //dig = 123; int div[4]; div[1] = digs[dig%10]; dig = dig/10; div[2] = digs[dig%10]; div[3] = digs[dig/10]; for(j=3;j>0;j--){ tmp = div[j]; for(i=8;i>0;i--){ if(tmp & 0x80){ REG_DATA_ON } else {REG_DATA_OFF} tmp <<=1; REG_CLK } } } int main(void){ int i=1; REG_DDR = (1<<REG_PIN_DATA)|(1<<REG_PIN_CLK); REG_PORT = (0<<REG_PIN_DATA)|(0<<REG_PIN_CLK); cd4094_init(); //cd4094(2); while(i<999){ _delay_ms(1000); cd4094(i); i++; } return 0; } Вот такая схема
  11. Пишу прошивку для управления всяким с пульта от телека, столкнулся с непонятным мне поведением программы (об этом ниже). Прошивка: #define F_CPU 4800000L // 4.8 Мгц #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define INVERT_PIN(x) PORTB ^= x /* PB2 (7) - реле (ВЫХОД). PB1 (PCINT1) (6) - ИК-приёмник (ВХОД). PB0 (PCINT0) (5) - сенсорная панель (ВХОД). PB3 (2) - светодиод (ВЫХОД). PB4 (PCINT4) (3) - кнопка (ВХОД). */ volatile char is_sensor_active = 0; volatile unsigned int rc_code = 0; volatile unsigned int etalon_rc_code = 0; // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__delay_1gad22e7a36b80e2f917324dc43a425e9d3.html // 262.14 / 4.8 = 54.61 мс - это максимальная задержка для данной частоты, до которой можно использовать _delay_ms. void delay_ms(unsigned int period) { while(--period) { _delay_ms(1); } } ISR(PCINT0_vect) { is_sensor_active = 1; } int main() { DDRB = 0b00001100; // Срабатывание прерывания при смене логического уровня на ножках. MCUCR = 0b00000001; // Прерывание генерятся при изменении уровня на ножках. GIMSK = 0b00100000; // Выбор генерящих прерывание пинов. PCMSK = 0b00000010; sei(); while(1) { if( is_sensor_active ) { cli(); rc_code = 0; for( int i = 0; i < sizeof(rc_code) * 8; ++i) { rc_code = (rc_code << 1) + ((PINB & 0b00000010) >> 1); _delay_ms(16); } if( etalon_rc_code == 0) etalon_rc_code = rc_code; if( etalon_rc_code == rc_code) { INVERT_PIN(0b00000100); } else { for( int i = 0; i < 10; ++i) { INVERT_PIN(0b00001000); _delay_ms(30); } } is_sensor_active = 0; delay_ms(240); sei(); } } return 0; } Как я ожидаю она должна работать: как только на ножке 6 сменится логический уровень, с ножки же 6 будет считано четырехбайтовое беззнаковое целое, принято за эталон команды и на ножке 7 установится лог. 1. При повторном зажигании прерывания снова будет считана команда, сравнена с эталонной и, если совпадает, инвертируется ножка 7. В противном случае помигать ножкой 2. Как оно на самом деле работает: вне зависимости от была ли команда верной или нет, контроллер дергает ножкой 2. Отсюда я делаю вывод, прерывание почему-то зажигается дважды. Но ведь не должно же! Вопрос: что же я упустил, приводящее к такому поведению? При обработке команды я прерывания запрещаю же, потом обратно включаю.
  12. Добрый день. Имеется ардуина, которая на int0 по прерываниям меряет частоту (скорость с приборной доски авто). Хочу включать в теле программы прерывание int0 только в нужные моменты, но не запрещать вообще все прерывания, а только INT0 включать-выключать. Как это сделать? Второй вопрос. Захотелось добавить управление с ИК-пульта (там тоже по прерываниям работает, но все ньюансы скрыты внутри библиотеки), при этом наблюдается какой-то конфликт c функциями Tone или Delay - звуковые сигналы вместо гудков превращаются в щелчки. Пока функция вывода звуковых сигналов не вызывалась - всё работает. Как пошли - ИК-команды не ловятся. Как найти, почему ИК-команды перестают ловится после вызова такой процедуры? void rukabeep() { tone (17,3000); delay(200); noTone(17); } P.S. работа с ИК пультом устроена так: библиотека IRremote_a10.zip void setup() { //start IR reciver irrecv.enableIRIn(); } в лупе функция if (irrecv.decode(&results)) { lcd.print(results.value); irrecv.resume(); // Receive the next value }
  13. UPD Прошу прощения, нашлась ошибка, производился декремент постоянного регистра. Изучаю авр и столкнулся с непреодолимой для меня проблемой. Простая программа АЦП>програмный делитель>шим. Регистр, в котором постоянно хранится число сдвигов для деления всё время сбрасывается в 0, при этом при этом установленный бит в порте не сбрасывается(сделал для проверки). Не важно, записан ли регистр в РЕСЕТ или в прерывании через кнопку, всё равно происходит сброс. Как такое может быть? Это происходит при моделировании в Протеусе, в симуляторе сброса нет, правда я не знаю как там вызывать прерывания, просто переставляю курсор. Сторожевой таймер вроде отключён и програмно и в протеусе. Что я делаю не так? Помогите новичку. .def temp1=r16 .def temp2=r17 .def div1=r18 .def div2=r19 .cseg .org 0x0000 rjmp RESET reti//1 rjmp vol//2 reti//3 reti//4 reti//5 reti//6 reti//7 rjmp adcpwm reti//9 reti//10 reti//11 reti//12 reti//13 reti//14 reti//15 RESET: ldi r16, (0<<WDRF)// остановка ст. таймера. out MCUSR, r16 ; Write logical one to WDCE and WDE ; Keep old prescaler setting to prevent unintentional Watchdog Reset in r16, WDTCR ori r16, (1<<WDCE)|(1<<WDE) out WDTCR, r16 ; Turn off WDT ldi r16, (0<<WDE) out WDTCR, r16 ldi temp1,0b00000011 out ddrb,temp1 ldi temp1,0b00011000 out portb,temp1 ldi temp1,0b11000011 out tccr0a,temp1 ldi temp1,0b00000001 out tccr0b,temp1 ldi temp1,0b00100001//УСТАНОВЛЕН СДВИГ ВЛЕВО out admux,temp1 ldi temp1,0b11101111 out adcsra,temp1 ldi temp1,0b00000000 out adcsrb,temp1 ldi temp1,0b00000000 out mcucr,temp1 ldi temp1,0b00100000 out gimsk,temp1 ldi temp1,0b00011000 out pcmsk,temp1 ldi div1,3// запись коэф деления в постоянный регистр sei start: rjmp start adcpwm:// прерывание АЦП--------------------------------------------- in temp1,adcl in temp2,adch mov div2,div1 // запись коэф. деления из постоянного рег во временный tst div2//деление breq zap l1: lsr temp2 ror temp1 dec div1 brne l1 zap://запись в шим out ocr0a,temp2 out ocr0b,temp2 reti VOL://прерывание кнопки---------------------------------------------------- ldi div1,3// запись коэф деления в постоянный регистр sbi portb,1//индикатор прерывания reti
  14. Добрый день, по ходу работы над 7-ми сегментными часами на ATmega8515 вылезла проблема с прерываниями, по счетчику. Перелопатил кучу информации и даташит, но в данном виде программы прерывания не работают, в чем может быть проблема? #define F_CPU 8000000 #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define digit_display_time 10 unsigned char milliseconds, seconds, ten_seconds, minutes, ten_minutes, hours, ten_hours; ISR(TIMER1_COMPA_vect) { milliseconds++; TCNT1H=0x00; TCNT1L=0x00; if (milliseconds >= 1000 ) { milliseconds = 0; seconds++; }; if (seconds >= 10) { seconds = 0; ten_seconds++; }; if (ten_seconds >= 6) { ten_seconds = 0; minutes++; }; if (minutes >= 10) { minutes = 0; ten_minutes++; }; if (ten_minutes >= 6) { ten_minutes = 0; hours++; }; if (hours >= 10) { hours = 0; ten_hours++; }; if (ten_hours >= 2 && hours == 4) { ten_hours = 0; hours=0; }; } void timer_init() { //OCR1A=125; OCR1AH = 0b00000000;// 125 OCR1AL = 0b01111101; //Предделитель на х64 TCCR1B = (0<<CS12)|(1<<CS11)|(1<<CS10); //Прерывание по совпадению TC1 A TIMSK=(1<<OCIE1A); sei(); } int main(void) { timer_init(); unsigned char digits[10] = {63,6, 91, 79, 102, 109, 125, 7, 127, 111}; DDRA = 0b11111111; DDRC = 0b11111111; PORTC = 0b00000000; while(1) { PORTA = digits[seconds]; DDRC = 0b00001000; _delay_ms(digit_display_time); PORTA = digits[ten_seconds]; DDRC = 0b00000100; _delay_ms(digit_display_time); PORTA = digits[minutes]; DDRC = 0b00000010; _delay_ms(digit_display_time); PORTA = digits[ten_minutes]; DDRC = 0b00000001; _delay_ms(digit_display_time); } } Clock.rar
  15. Здравствуйте, столкнулся с такой проблемой: При использовании внешнего прерывания от кнопки INT0 выбирается один из режимов работы контроллера. Каждый режим состоит из длительного цикла (самый короткий 8 мин.). При обработке прерывания изменяется значение глобальной переменной. Состояние переменной проверяется лишь после окончания одного из циклов, что вызывает большую задержку времени до конца исполнения текущего цикла. Проверку переменной в цикл вставить не возможно из-за его и без того высокой нагрузки на систему. Как выход вижу переход при выполнении прерывания к началу программы. Подскажите как можно реализовать такой периход, либо иначе решить задачу. Код в упрощенном виде прилагаю. volatile int reg=0x00; interrupt [EXT_INT0] void ext_int0_isr(void) { reg=reg+1; delay_ms(50); if (reg>0x11) { reg=0x00; } } void regim0 (unsigned int x, y, z) { for (a=0; a<d; a++) { //…………… } } void regim2 (unsigned int x, y, z) { for (a=0; a<d; a++) { //………….. } } //………….. void regim11 (unsigned int x, y, z) { for (a=0; a<d; a++) { //………….. } } void main(void) { while (1) { switch (reg) case 0: regim0(x,y,z); break; case 1: regim1(x,y,z); break; //………….. case 11: regim11(x,y,z); break; } }
  16. Значит тема такая: Программа формирования ШИМ сигнала с коэффициентом заполнения 0,4 и 0,6, задаваемым по внешнему прерыванию от двух сигналов, и с периодом 5 кГц. ШИМ сигнал формируется по прерыванию от таймеров. Я написал программу по прерыванию от внешнего сигнала, но прерывание по таймеру не могу написать. Вот программа работающая, но в которой нет прерывания по таймеру: TIME EQU -(200) JMP START ORG 20H START: MOV IE,#10000101B ;установка битов регистра разрешения прерываний CALL SETUPTIMER ;настройка таймера MOV R1,#-126 MOV R2,#-40 MOV TCON,#00000101B ;разрешение внешних прерываний по низкому уровню сигнала JMP TIM TIM: CALL FORM ;подпрограмма формирования сигнала JMP TIM ;зациклить на выводе SETUPTIMER: MOV TMOD,#00000001b ;установка таймера в режим 1 MOV P0,#0 ;сброс порта ввода-вывода RET DELAY1: MOV TH0,#11111111B ;настройка таймера MOV TL0,R1 SETB TR0 ;запуск таймера JNB TF0,$ ;ожидание переполнения CLR TF0 ;сброс флага переполнения CLR TR0 ;остановка таймера RET DELAY2: MOV TH0,#11111111B MOV TL0,R2 SETB TR0 JNB TF0,$ CLR TF0 CLR TR0 RET FORM: MOV P0,#200 ;вывод точки в порт CALL DELAY1 ;вызов п/п задержки на высоком уровне MOV P0,0 ;вывод в порт точки низкого уровня CALL DELAY2 ;вызов п/п задержки на низком уровне RET ORG 0003H ;адрес источника прерывания INT0 CLR TR0 ;остановка таймера CLR EA ;запрет прерываний MOV R1,#-45 MOV R2,#-120 SETB EA ;разрешение прерываний SETB TR0 ;запуск таймера RETI ;возврат из п\п прерывания ORG 0013H ;адрес источника прерывания INT1 CLR TR0 CLR EA MOV R1,#-126 MOV R2,#-40 SETB EA SETB TR0 RETI END Как изменить ее так, чтобы вместо подпрограмм задержек по таймеру включалась п\п прерывания?
  17. Всем доброе утро и спасибо за то что хоть глянули топик! Срочно нужна ваша помощь! Собственно проблема - нужно сделать частотомер на авр (Atmega8) и обеспечить передачу данных по UART. Вот то что есть уже у меня: program MAN; var rec,send,setup,cons,start,a,i:integer; var f,freq:longint; var outp,inp:string [23]; label lbl; procedure Compare(); iv IVT_ADDR_TIMER1_COMPA; begin inc(i); if i=1 then begin INT0_bit:=1; TCNT1H:=0x00; TCNT1L:=0x00; DDC1_bit:=1; end else if i=2 then begin TCCR1B:=0; INT0_bit:=0; TCNT1H:=0x00; TCNT1L:=0x00; i:=0; IntToStr(f,outp); UART1_Write_Text(outp); DDC1_bit:=0; f:=0; end; end; procedure int0p(); iv IVT_ADDR_INT0; begin inc(f); end; begin SREG_I_bit:=1; TCCR1B:=0; OCIE1A_bit:=1; OCR1AH:= 0x7a; OCR1AL:= 0x12; ISC00_bit:=1; ISC01_bit:=1; INT0_bit:=0; UART1_Init(600); PINB0_bit:=1; DDC0_bit:=0; DDC1_bit:=0; DDC2_bit:=1; While TRUE do begin if (UART_Data_Ready() = 1) then begin UART1_Read_Text(inp,'/',23); UART1_Write_Text(inp); if strstr(inp,'get') <> 0xFFFF then TCCR1B:=4; end; end; end. Но при запросе с ПК он выдает все что угодно, но не частоту (ресейв переменной сделал специально. что б смотреть не потерялось ли чего). Или напишите структурную схему частотомера (прерывание по int0 или t1). Заранее спасибо!
  18. Не так давно программирую МК какие подвернуться. Никак не могу взять в толк одну вещь: Если мы тактируем какую нибудь периферию от таймера с определенной частотой, то имеем примерно следующее: инициализация генератора тактовых импульсов, инициализация периферии, инициализация таймера. Далее таймер считает, считает, считает -> досчитывает и генерирует прерывание. И мы что-то делаем. Например моргаем диодом. Часики продолжают тикать, пока обрабатывается прерывание, верно? А если надо опросить много кнопок, АЦП, послать посылку,...? Пройдет куча тактов (причем не всегда одинаковое количество) и уже нельзя будет сказать, например, что мы опрашиваем АЦП каждые xxx наносекунд, ведь частота прерываний поплыла. Верно?
  19. Ковыряю в Proteus свой виртуальный ATtiny2123 в попытках написать мигание светодиодом без delay. Копал в сети информацию на эту тему, но толком ничего не понял, хотя судя по всему это надо иметь дело с прерываниями, если правильно понял. Задача очень простая, мигать диодами не используя _delay_ms(). Перешел на изучение AVR с Arduino, так там считалось такое по таймеру. Функция millis(), которая считала миллисекунды с начала выполнения Arduino, но в AVR ничего готового такого не нашел. Кто может доступно объяснить про эту тему и все что с ней связано? Заранее благодарен.
  20. Доброго времени суток, включив в схему кварц на 8МГц задался вопросом, как настроить прерывани я таймера с интервалом 1 секунда void SetupTIMER1 (void) { TCCR1B = (1<<CS02)|(1<<CS01); //External clock source on T0 pin. Clock on falling edge. прерывания от внешнего источника TCNT1 = 65536-62439; //коррекция счетчика, чтобы время было ровно 1 секунда - данный участок кода я не понял /* Enable timer 1 overflow interrupt. */ TIMSK = (0<<TOIE1); } Подкорректируйте, пожалуйста, мой код, если он неверен, и помтгите разобраться со строкой "TCNT1 = 65536-62439; ", а именно как скорректировать счётчик на время 1 секунда Заранее спасибо
  21. Прерывания

    Приветствую всех! Я только-только начал иметь иметь дело как с контроллерами, так и с ассемблером. Пишу сейчас в Atmel Studio 6 для ATMega16. Чтобы получше разобраться, вбил я такой код: .include "m16def.inc" //------------------------------- .CSEG .ORG $000 ; (RESET) RJMP Reset .ORG $002 RETI ; (INT0) External Interrupt Request 0 .ORG $004 RETI ; (INT1) External Interrupt Request 1 .ORG $006 RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match .ORG $008 RETI ; (TIMER2 OVF) Timer/Counter2 Overflow .ORG $00A RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event .ORG $00C RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A .ORG $00E RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B .ORG $010 RETI ; (TIMER1 OVF) Timer/Counter1 Overflow .ORG $012 RETI ; (TIMER0 OVF) Timer/Counter0 Overflow .ORG $014 RETI ; (SPI,STC) Serial Transfer Complete .ORG $016 RJMP RX_OK ; (USART,RXC) USART, Rx Complete .ORG $018 RETI ; (USART,UDRE) USART Data Register Empty .ORG $01A RETI ; (USART,TXC) USART, Tx Complete .ORG $01C RETI ; (ADC) ADC Conversion Complete .ORG $01E RETI ; (EE_RDY) EEPROM Ready .ORG $020 RETI ; (ANA_COMP) Analog Comparator .ORG $022 RETI ; (TWI) 2-wire Serial Interface .ORG $024 RETI ; (INT2) External Interrupt Request 2 .ORG $026 RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match .ORG $028 RETI ; (SPM_RDY) Store Program Memory Ready .ORG INT_VECTORS_SIZE ; Конец таблицы прерываний RX_OK: IN R16,UDR RETI Reset: LDI R16,Low(RAMEND) OUT SPL,R16 LDI R16,High(RAMEND) OUT SPH,R16 SEI LDI R17,(1<<RXCIE) OUT UCSRB,R17 M1: NOP NOP NOP NOP RJMP M1 Начну с того, что команда SEI не меняет значение флага I регистра SREG. Но это еще не все. Если забить и установить этот флаг вручную, то при установки флага прерывания RXC в регистре UCSRA ничего не происходит - на следующий же такт он сам возвращается в исходное состояние, а контроллер продолжает бегать циклом по NOP. Что я забыл, что не так?
  22. Здравствуйте! Помогите пожалста начинающему. У меня отладочная плата на базе STM32f103RE Диодами помигал, прерывание по кнопке сделал, дисплей зажег. Нужно ковырять интерфейсы, до этого никогда не имел с ними дела, без подсказок мне сложно разобраться. Как работают примеры не понятно Для начала хочу хоть что-нибудь послать по CAN. Как я понял, посылки в CAN формируются без адреса, устройство само определяет получать ли ей посылку или отвергнуть. Сам кадр выглядит так: Не могу понять для себя последовательность действий при формировании кадра. Сейчас я это вижу примерно так: 1) Разрешаю тактирование портов ввода-вывода, CAN, альтернативных функций порта(в моем случае) 2) Настраиваю порты ввода-вывода. Tx - выход push-pull, Rx - input with pull-up/pull-down 3) Настраиваю CAN: -режим работы. к примеру ставлю нормал -выставляю baudrate. в регистр нужно заносить значение в герцах в шестнадцатеричной форме? -задаю длину посылки, выставляю RTR и IDE -что за регистр NVIC? и почему его нет в даташите, а в примерах он настраивается: NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; -собираю посылку и отправляю. на этом этапе тоже не понятно, посылка собирается с помощью массива? как отправить посылку? и еще пара вопросов по СИ: 1) void Init_RxMes(CanRxMsg *RxMessage); в скобках перечисляются входные параметры функции, что значит звездочка? и почему запятой нет? 2) uint8_t KeyNumber = 0x0; unit8_t - говорит о том, что число восьмибитное? 3) NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); здесь собирается структура и результат обрабатывается через NVIC_Init()? зачем тогда нужен символ "&"? простите за глупые вопросы