|
Внешние прерывания, STM32F103VB |
|
|
|
Jul 27 2014, 06:35
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Я пытаюсь включить внешние прерывания в свою программу на STM32F103VB. CODE void ExtIntInit(void) { // enable clock for Alternate Function RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
//BUT - PE0 GPIOE->CRL &= ~GPIO_CRL_MODE0; //Configure as input GPIOE->CRL &= ~GPIO_CRL_CNF0; GPIOE->CRL |= GPIO_CRL_CNF0_1; //input with pull-up/pull-down resistor GPIOE->BSRR |= GPIO_BSRR_BS0; //set pull-up //ENC1 - PE1 GPIOE->CRL &= ~GPIO_CRL_MODE1; //Configure as input GPIOE->CRL &= ~GPIO_CRL_CNF1; GPIOE->CRL |= GPIO_CRL_CNF1_1; //input with pull-up/pull-down resistor GPIOE->BSRR |= GPIO_BSRR_BS1; //set pull-up //ENC2 - PE2 GPIOE->CRL &= ~GPIO_CRL_MODE2; //Configure as input GPIOE->CRL &= ~GPIO_CRL_CNF2; GPIOE->CRL |= GPIO_CRL_CNF2_1; //input with pull-up/pull-down resistor GPIOE->BSRR |= GPIO_BSRR_BS2; //set pull-up
//interrupt source PE AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PE; //PE0 - BUT AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI1_PE; //PE1 - ENC1 AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI2_PE; //PE2 - ENC2 AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI3_PE; //PE3 - ENC3
//interrupt edge EXTI->RTSR |= 0; //EXTI_RTSR_TR0; //rising EXTI->FTSR |= EXTI_FTSR_TR0; //falling EXTI->FTSR |= EXTI_FTSR_TR1; //falling EXTI->FTSR |= EXTI_FTSR_TR2; //falling EXTI->FTSR |= EXTI_FTSR_TR3; //falling
//enable ext interrupt EXTI->IMR |= EXTI_IMR_MR0; EXTI->IMR |= EXTI_IMR_MR1; EXTI->IMR |= EXTI_IMR_MR2; EXTI->IMR |= EXTI_IMR_MR3;
NVIC_EnableIRQ(EXTI0_IRQn); NVIC_EnableIRQ(EXTI1_IRQn); NVIC_EnableIRQ(EXTI2_IRQn); NVIC_EnableIRQ(EXTI3_IRQn); }
И обработчик CODE void EXTI0_IRQHandler(void) //button pressed { EXTI->PR = EXTI_PR_PR0; //clear flag??? TIM4->CNT = 0; TIM4->CR1 |= TIM_CR1_CEN; //but_int = true; //NVIC_EnableIRQ(TIM7_IRQn);
} void EXTI1_IRQHandler(void) //encoder1 { EXTI->PR = EXTI_PR_PR1; //clear flag??? enc1_int = 1; if(DIR1) { mot1_position++; } else { if(mot1_position > 0) { mot1_position--; } } }
void EXTI2_IRQHandler(void) //encoder2 { EXTI->PR = EXTI_PR_PR2; //clear flag??? if(DIR2) { mot2_position++; } else { if(mot2_position > 0) { mot2_position--; } } }
void EXTI3_IRQHandler(void) //encoder3 {
EXTI->PR = EXTI_PR_PR3; //clear flag??? if(DIR3) { mot3_position++; } else { if(mot3_position > 0) { mot3_position--; } } }
До этого кода все работает нормально. После включения этого куска кода камень умирает и не реагирует ни на что. Я уже пару дней бьюсь над проблемой. Читаю документацию вдоль и поперек не могу понять где проблема.
|
|
|
|
|
 |
Ответов
|
Jul 30 2014, 07:03
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
да фигня... общий принцип перевести все входы под единый клок внутри ПЛИС и забыть об этом. CODE `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: *** // Engineer: *** // // Create Date: *** // Design Name: // Module Name: SPIComModule // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // "spi_cs" and "data_rdy" signal must be in // stable state before any "spi_clk" actions // min 2 "clk" for "data_rdy" // and 2 "clk" for "spi_cs" // ////////////////////////////////////////////////////////////////////////////////// module SPIComModule_v4_00( clk, //основной клок spi_cs, //сигнал выбора SPI spi_clk, //SPI клок данных spi_in, //входные данные SPI spi_out, //выходные данные SPI module_sel, //выбор модуля submodule_sel, //выбор подмодуля data_to_module, //данные для модуля data_from_module, //данные от модуля wr_rd_sync, //сигнал синхронизации чтения - записи wr_strb, //строб записи wr_ack, //подтверждение записи rd_strb, //строб чтения rd_ack, //подтверждение чтения check_sum_ok, //сигнал подтверждения правильной контрольной суммы data_write_done, //сигнал подтверждения записи данных data_rdy //сигнал готовности данных для чтения );
//================================================================================ == parameter MODULE_DATA_SIZE = 32; //размер данных модуля parameter MODULE_ADDR_SIZE = 4; //размер поля адреса parameter MODULE_ADDR_VECTOR_SIZE = (32'b01 << MODULE_ADDR_SIZE); //размер вектора выбора модуля (4 бита адрес) parameter SUB_ADDR_SIZE = 3; //размер поля подадреса parameter SUB_ADDR_VECTOR_SIZE = (32'b01 << SUB_ADDR_SIZE); //размер вектора выбора подмодуля (3 бита подадрес)
parameter READ_DIRRECTION_VAL = 1; //значение бита при котором идет чтение parameter ADDR_FIELD_SIZE = 8; //8 бит поле адреса parameter CHECKSUM_FIELD_SIZE = 8; //8 бит поле контрольной суммы localparam DATA_FIELD_SIZE = MODULE_DATA_SIZE; //размер поля данных //размер регистра расчета длинны сообщения для определения //окончания приема parameter MES_LEN_COUNTER_SIZE = 6; //размер регистра расчета длинны слова контрольной суммы //для определения окончания приема очередного слова parameter CHECKSUM_LEN_COUNTER_SIZE = 3; //контрольная сумма по всем сообщению должна дать 0 //чтобы полностью нулевое сообщение не прошло как верное //начинаем считать сумму с этого значения parameter START_CHECKSUM_VAL = 'hA5; //================================================================================ == input clk; input spi_cs; input spi_clk; input spi_in; output spi_out; output reg [MODULE_ADDR_VECTOR_SIZE - 1 : 0] module_sel = 0; output reg [SUB_ADDR_VECTOR_SIZE - 1 : 0] submodule_sel = 0; output reg [MODULE_DATA_SIZE - 1 : 0] data_to_module = 0; input [MODULE_DATA_SIZE - 1 : 0] data_from_module; //этот сигнал должен быть лишен мета-стабильности //во внешних схемах input wr_rd_sync; output wr_strb; input wr_ack; output rd_strb; input rd_ack; output reg check_sum_ok = 0; output reg data_write_done = 0; output reg data_rdy = 0; //================================================================================ == //регистры для задания состояние строба чтения и записи //эти регистры задает схема, а выходное значение получается //с учетом сигнала синхронизации reg wr_strb_reg = 0; reg rd_strb_reg = 0; //если разрешена запись или чтение, выдаем наружу стробы assign wr_strb = (wr_strb_reg & wr_rd_sync); assign rd_strb = (rd_strb_reg & wr_rd_sync); //для синхронизации 2 клоковых доменов //основного и SPI используем систему семафоров //задание и подтверждение задания reg need_start_recive = 0; //необходимо начать прием с 1 клоком SPI reg need_start_recive_ack = 0; //подтверждение, прием начат reg recive_done = 0; //окончание приема //так как сигнал из другого клокового домена //пропустим его через 2 триггера, это создаст //доп задержку на стабилизацию данных //по констрайнам частота процессора в 2 раза выше частоты SPI //значит через 2 клока данные SPI гарантированно верны reg recive_done_1 = 0; reg recive_done_2 = 0; reg recive_done_ack = 0; //подтверждение окончания приема reg need_start_transllate = 0; //необходимо начать передачу данных reg need_start_transllate_ack = 0; //передача данных начата //вектор входного сообщения localparam FULL_MESSAGE_LEN = ADDR_FIELD_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE; reg [FULL_MESSAGE_LEN - 1 : 0] input_data_vector = 0; //для удобства работы разделим поля входного вектора wire [DATA_FIELD_SIZE - 1 : 0] data_w; assign data_w = input_data_vector[DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: DATA_FIELD_SIZE]; wire [SUB_ADDR_SIZE - 1 : 0] subaddr_w; assign subaddr_w = input_data_vector[SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: SUB_ADDR_SIZE]; wire [MODULE_ADDR_SIZE - 1 : 0 ] addr_w; assign addr_w = input_data_vector[MODULE_ADDR_SIZE + SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: MODULE_ADDR_SIZE]; wire read_direction_w; assign read_direction_w = input_data_vector[1 + MODULE_ADDR_SIZE + SUB_ADDR_SIZE + DATA_FIELD_SIZE + CHECKSUM_FIELD_SIZE - 1 -: 1]; //вектор расчета контрольной суммы reg [CHECKSUM_FIELD_SIZE - 1 : 0] checksum_calc_vector = START_CHECKSUM_VAL; //вектор приема данных для расчета контрольной суммы reg [CHECKSUM_FIELD_SIZE - 1 : 0] checksum_vector = 0; //вектор выходных данных, на 1 бит меньше чем данные //так как первый отправляемый бит в него не сохраняется reg [DATA_FIELD_SIZE - 2 : 0] output_vector = 0; //значение выходного бита данных SPI должно быть готово //до первого клока, еще до защелки данных в сдвиговый регистр //поэтому первый бит берется из входного вектора //а последующие уже из сдвигового регистра //в начальный момент будет стоять семафор assign spi_out = (need_start_transllate != need_start_transllate_ack) ? data_from_module [MODULE_DATA_SIZE - 1] : //начальный момент output_vector[MODULE_DATA_SIZE - 2]; //последующие посылки (вектор на 1 бит меньше данных) //счетчик длинны сообщения reg [MES_LEN_COUNTER_SIZE - 1 : 0] mes_len_counter = 0; //счетчик длинны слова контрольной суммы reg [CHECKSUM_LEN_COUNTER_SIZE - 1 : 0] checksum_len_counter = 0; //================================================================================ == // обработка основного клока //================================================================================ == always @(posedge clk) begin //-------------------- переход между клоковыми доменами recive_done_1 <= recive_done; recive_done_2 <= recive_done_1; //-------------------- обмен данными if(spi_cs == 1'b1) //если нет выбора SPI begin //чип селект имеет гарантированную паузу, он асинхронный //гарантированная пауза приведет схему в правильное состояние //выборы адреса - one hot, один бит в векторе, //при снятии не может так получиться что бит измениться //или возникнут еще какие-то соседние биты, //потому даже если адрес изменится до снятия wr(rd)_strb //так как сигнал cs асинхронный, это не страшно, другие //адреса не выберутся и неправильных транзакций не будет //значение битов ответов тоже не важно, если чип селект //вверху их уже не проверяют
//подготовимся к приему следующего сообщения //первый фронт SPI клока - начало приема need_start_recive <= ~need_start_recive_ack; //снимем все стробы wr_strb_reg <= 0; rd_strb_reg <= 0; //снимем все выборы, module_sel <= 0; submodule_sel <= 0; //снимаем все ответы check_sum_ok <= 0; data_write_done <= 0; data_rdy <= 0; //на всякий случай, если было поднятие чипселекта //до окончания обмена, снимем флаг окончания приема recive_done_ack <= recive_done_2; end else //если есть выбор SPI begin if(recive_done_2 != recive_done_ack) //если закончен прием begin //ставим подтверждение обработки флага recive_done_ack <= recive_done_2;
//если сошлась контрольная сумма //последние сложение надо сделать в этой процедуре //так как после приема последнего бита //нет больше тактов (клоков SPI) на выполнение if((checksum_calc_vector + checksum_vector) == {CHECKSUM_FIELD_SIZE{1'b0}}) begin check_sum_ok <= 1'b1; //ставим признак //ставим выбор модуля и подадреса //сразу производим частичную дешифрацию адреса module_sel <= ({{(MODULE_ADDR_VECTOR_SIZE - 1){1'b0}}, 1'b1} << $unsigned (addr_w)); submodule_sel <= ({{(SUB_ADDR_VECTOR_SIZE - 1){1'b0}}, 1'b1} << $unsigned (subaddr_w)); if(read_direction_w == READ_DIRRECTION_VAL) //если режим чтения begin rd_strb_reg <= 1'b1; //строб чтения //отмечаем что нужно будет начать передачу //захват данных в регистр произойдет по //SPI клоку, а его выдаст мастер только после //получения сигнала готовности данных //так что это значение можно тут выставить //и не заботится о нем, даже если будет прерывание обмена //без фазы чтения need_start_transllate <= ~need_start_transllate_ack; end else //режим записи begin data_to_module <= data_w; //выставляем данные wr_strb_reg <= 1'b1; //строб записи end end //контрольная сумма end //закончен прием //если не будет признака окончания приема //не будет проверки контрольной суммы //и не будет запросов на чтение или запись //и сигналы ниже не появятся //если есть запрос на запись и подтверждение if((wr_strb_reg == 1'b1)&&(wr_ack == 1'b1)) data_write_done <= 1'b1; //отмечаем что данные записаны //если есть запрос на чтение и подтверждение if((rd_strb_reg == 1'b1)&&(rd_ack == 1'b1)) data_rdy <= 1'b1; //отмечаем что данные готовы end //есть выбор SPI end //конец обработки клока //================================================================================ == // обработка клока SPI //================================================================================ == //выбор SPI не проверяем, так как без выбора не //пройдет конец обмена, весь обмен идет внутри //одного выбора, клоков вне обмена нет always @(posedge spi_clk) begin //---------------------------------------------------------------- if (need_start_recive != need_start_recive_ack) //если начало приема ы begin //отмечаем начало приема need_start_recive_ack <= need_start_recive; //сохраняем первый принятый бит input_data_vector <= {{(FULL_MESSAGE_LEN - 1){1'b0}},spi_in}; checksum_vector <= {{(CHECKSUM_FIELD_SIZE - 1){1'b0}},spi_in}; //сохраняем начальное значение вектора расчета контрольной суммы checksum_calc_vector <= START_CHECKSUM_VAL; //заряжаем счетчики, первый бит уже принят, //окончание приема всего сообщения по равенству нулю //счетчик всего сообщения на 1 бит меньше чтобы //он стал нулем в момент приема последнего бита //а не после приема, вместе с приемом последнего //бита выставиться и признак окончания приема mes_len_counter <= (FULL_MESSAGE_LEN - 2); checksum_len_counter <= (CHECKSUM_FIELD_SIZE - 1); end else //прием begin //уменьшаем счетчики с каждым принятым битом mes_len_counter <= mes_len_counter - 1'b1; checksum_len_counter <= checksum_len_counter - 1'b1; //прием сообщения, сдвигаем входной вектор дополняя входным битом input_data_vector <= {input_data_vector[FULL_MESSAGE_LEN - 2 : 0], spi_in}; //параллельно сохраняем вектор контрольной суммы checksum_vector <= {checksum_vector [CHECKSUM_FIELD_SIZE - 2 : 0], spi_in}; //если приняли все сообщение if(mes_len_counter == 0) recive_done <= ~recive_done_ack; //отмечаем окончание приема //если приняли очередное слово контрольной суммы if(checksum_len_counter == 0) begin //заряжаем счетчик заново checksum_len_counter <= (CHECKSUM_FIELD_SIZE - 1); //добавляем принятый вектор в сумму checksum_calc_vector <= checksum_calc_vector + checksum_vector; end end //прием //----------------------------------------------------------------- //значение передаваемых данных во время приема не важны, //потому всегда передаем, к фазе передачи данные будут //запрошены и корректно обновлены if (need_start_transllate != need_start_transllate_ack) //если начало передачи begin //отмечаем начало передачи need_start_transllate_ack <= need_start_transllate; //сохраняем данные от модуля без старшего бита, //так как первый бит уже передан (взят из данных на отправку) //после этого такта, на выход будет передаваться старший бит //этого вектора output_vector <= data_from_module[DATA_FIELD_SIZE - 2 : 0]; end else //передача begin //просто сдвигаем вектор данных //значение дополнения не важно output_vector <= (output_vector << 1); end //передача end //конец обработки клока SPI endmodule
wr_rd_sync - этот сигнал в 1 зажмите, он для синхронизации служит, это для нашей специфики было нужно.
|
|
|
|
Сообщений в этой теме
Jenya7 Внешние прерывания Jul 27 2014, 06:35 AHTOXA GPIO затактировать забыли? Jul 27 2014, 06:55 Jenya7 Цитата(AHTOXA @ Jul 27 2014, 11:55) GPIO ... Jul 27 2014, 07:25 Genadi Zawidowski выясните для начала, нет ли ситуации что "кам... Jul 27 2014, 10:02 Jenya7 Цитата(Genadi Zawidowski @ Jul 27 2014, 16... Jul 27 2014, 10:16  smk Цитата(Jenya7 @ Jul 27 2014, 13:16) Я так... Jul 27 2014, 12:33   adnega Цитата(smk @ Jul 27 2014, 16:33) EXTI-... Jul 27 2014, 12:46    smk Цитата(adnega @ Jul 27 2014, 15:46) Так т... Jul 27 2014, 14:04     adnega Цитата(smk @ Jul 27 2014, 18:04) Но ведь ... Jul 27 2014, 14:09      smk Цитата(adnega @ Jul 27 2014, 17:09) Может... Jul 27 2014, 14:39       Jenya7 Цитата(smk @ Jul 27 2014, 20:39) Код#defi... Jul 27 2014, 16:00 adnega Цитатачто так что так
В таком случае предлагаю по... Jul 27 2014, 16:45 Сергей Борщ Цитата(adnega @ Jul 27 2014, 19:45) Напри... Jul 27 2014, 19:20 Golikov A. ЦитатаPS. В cortex-m хорошо, что прерывания защелк... Jul 27 2014, 19:22 adnega Если использовать EXTI не самоцель, то для получен... Jul 27 2014, 20:18 Jenya7 Цитата(adnega @ Jul 28 2014, 02:18) Если ... Jul 28 2014, 09:36 Jenya7 Проблема закралась с неожиданной стороны. На плате... Jul 28 2014, 05:50 KnightIgor Цитата(Jenya7 @ Jul 28 2014, 07:50) Но вс... Jul 28 2014, 13:54 hd44780 Jenya7, посмотрите, может ремап Вам поможет.
Мне н... Jul 28 2014, 10:07 Jenya7 Цитата(hd44780 @ Jul 28 2014, 16:07) Jeny... Jul 28 2014, 10:16  adnega Цитата(Jenya7 @ Jul 28 2014, 14:16) Я смо... Jul 28 2014, 13:13 Jenya7 Я тут посмотрел...возможно я таки найду свободные ... Jul 28 2014, 14:12 adnega Цитата(Jenya7 @ Jul 28 2014, 18:12) Кстат... Jul 28 2014, 16:27  Jenya7 Golikov A.
Спасибо за подробное объяснение.
Цита... Jul 29 2014, 06:15   adnega Цитата(Jenya7 @ Jul 29 2014, 10:15) Тут к... Jul 29 2014, 08:30    Jenya7 Цитата(adnega @ Jul 29 2014, 14:30) Может... Jul 29 2014, 10:29     adnega Цитата(Jenya7 @ Jul 29 2014, 14:29) Но я ... Jul 29 2014, 12:46      Jenya7 Цитата(adnega @ Jul 29 2014, 18:46) А дву... Jul 29 2014, 13:13 Golikov A. Опять нужна лекция... попробуем укороченный вариан... Jul 28 2014, 15:52 Golikov A. ПЛИС надо ставить... Jul 29 2014, 13:41 Jenya7 Цитата(Golikov A. @ Jul 29 2014, 19:41) П... Jul 29 2014, 13:52 Golikov A. ага, где то полдня работы...
у нас 5 моторами рули... Jul 29 2014, 19:02 Jenya7 Цитата(Golikov A. @ Jul 30 2014, 01:02) а... Jul 30 2014, 05:20  adnega Цитата(Jenya7 @ Jul 30 2014, 09:20) Это к... Jul 30 2014, 06:35   Jenya7 Цитата(adnega @ Jul 30 2014, 12:35) STM32... Jul 30 2014, 07:07 adnega А если вместо ПЛИС поставить мелкоту, типа STM32F0... Jul 29 2014, 19:23 Golikov A. ЦитатаМожет подгоните имплементацию парсера комман... Jul 30 2014, 06:19 Jenya7 Цитата(Golikov A. @ Jul 30 2014, 12:19) Е... Jul 30 2014, 06:27 Golikov A. RE: Внешние прерывания Jul 30 2014, 07:14 Jenya7 Перед тем как начать програмироать на ПЛИС я читал... Jul 30 2014, 07:30 DmitryM Цитата(Jenya7 @ Jul 30 2014, 11:30) Перед... Jul 30 2014, 07:59 Golikov A. Поскольку мне надо делать дело, а не быть в тренде... Jul 30 2014, 09:23
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|