реклама на сайте
подробности

 
 
> Внешние прерывания, STM32F103VB
Jenya7
сообщение Jul 27 2014, 06:35
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 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--; }
}
}

До этого кода все работает нормально. После включения этого куска кода камень умирает и не реагирует ни на что. Я уже пару дней бьюсь над проблемой. Читаю документацию вдоль и поперек не могу понять где проблема.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Golikov A.
сообщение Jul 30 2014, 07:03
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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 зажмите, он для синхронизации служит, это для нашей специфики было нужно.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- 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


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th August 2025 - 03:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.01869 секунд с 7
ELECTRONIX ©2004-2016