16.04.2014, 19:40
|
#4001
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
MaxiMuz79, дык возьмите и сделайте. SPL дает широкий спектр возможностей, но если в голове все еще АВРизм, то да, можно испохабить и STM.
|
|
|
|
16.04.2014, 19:56
|
#4002
|
Почётный гражданин KAZUS.RU
Регистрация: 13.10.2007
Адрес: Беларусь
Сообщений: 8,048
Сказал спасибо: 60
Сказали Спасибо 3,954 раз(а) в 2,309 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от MaxiMuz79
|
Интересно , а есть для STM32f(L) неважно какой серии набор(библиотека) макросов для работы с таймерами
|
Они слишком навороченные, поэтому скажем "библиотека" для таймера1 будет состоять из многих десятков частей, на каждый из режимов... С АЦП тоже десятки вариантов, и все не предусмотришь, т.к. вся периферия СТМ32 очень глубоко интегрирована друг в друга - тот же АЦП может синхронизироваться от таймеров и внешних прерываний... Если лично для вас СТМ32 слишком сложные - у вас всегда есть возможность перейти на ПИК/АВР со сравнительно примитивной периферией, и даже на голое с51 ядро
|
|
|
|
16.04.2014, 23:32
|
#4003
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от Easyrider83
|
SPL дает широкий спектр возможностей
|
дает но в местах где требуется как можно меньше времяни на обработку, в тех же прерываниях, SPL не помощник.
Похоже здесь каждый решает проблему как может , хотя думаю наверняка у когонибудь есть такие помошники-макросы...
Сообщение от niXto
|
Они слишком навороченные, поэтому скажем "библиотека" для таймера1 будет состоять из многих десятков частей, на каждый из режимов..
|
выход в том что под каждый режим тогоже таймера написать свой макрос , где пускай основные настройки будут прописаны через макроопределения и в параметрах будут задаваться только номер таймера, какие нибудь выходы/входы . Смысл в том чтобы не писать каждый раз
Цитата:
|
RCC-›APB1ENR |= RCC_APB1ENR_TIM2EN;//Тактирование таймера TIM2
TIM2-›CR1 |= TIM_CR1_ARPE;//Включен режим предварительной записи регистра автоперезагрузки
TIM2-›CCMR1 |= TIM_CCMR1_OC2PE;//Включен режим предварительной загрузки регистра сравнения
TIM2-›CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1);//OC2M = 110 - PWM mode 1
TIM2-›ARR = 23999;//Период выходного сигнала T = 1mS
TIM2-›CCR2 = 19200;//Длительность импульса. В данном случае Duty cycle = 80%
//TIM2-›CCER |= TIM_CCER_CC2P;//Полярность выходного сигнала
TIM2-›CCER |= TIM_CCER_CC2E;//Выход канала захвата/сравнения включен
|
а написать к примеру :
Цитата:
|
START_TIM_CAPT(2,CC2P,CC2E)
TIM_ARR(2)=23999;
|
.... ну это так, мысли вслух, фантазии и наверное предмет отдельной темы ...
Последний раз редактировалось MaxiMuz79; 16.04.2014 в 23:34.
|
|
|
|
16.04.2014, 23:38
|
#4004
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от niXto
|
вся периферия СТМ32 очень глубоко интегрирована друг в друга
|
Да друг в друга вроде нет особо ничего. Много устройств и возможность внутреннего подключения выходов одних устройства ко входам других. Обычная история - устройства и матрица входов и выходов.
|
|
|
|
16.04.2014, 23:49
|
#4005
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от MaxiMuz79
|
выход в том что под каждый режим тогоже таймера написать свой макрос , где пускай основные настройки будут прописаны через макроопределения и в параметрах будут задаваться только номер таймера, какие нибудь выходы/входы . Смысл в том чтобы не писать каждый раз
|
Заполнять структуру инициализации проще, чем вспоминать какой аргумент в Макросе за что отвечает.
|
|
|
|
16.04.2014, 23:57
|
#4006
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от Boba_spb
|
Заполнять структуру инициализации проще, чем вспоминать какой аргумент в Макросе за что отвечает.
|
но ведь в SPL вы же вспоминаете что и куда писать + кучу структур создаете, куча писанины ...
Последний раз редактировалось MaxiMuz79; 17.04.2014 в 10:22.
|
|
|
|
17.04.2014, 00:52
|
#4007
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Я не вспоминаю, я беру, однажды заполненую структуру, и заменяю в ней то, что необходимо.
|
|
|
|
17.04.2014, 14:15
|
#4008
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Для тех, кто мучился с I2C на STM32F10x делюсь библиотекой. DMA под I2C - роскошь, pooling - потеря времени. Идеально - прерывания.
Итак, инициализацию делаем по SPL. Все там хорошо и красиво:
Код:
|
I2C_InitTypeDef I2C_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStruct);
I2C_StructInit(&I2C_InitStruct);
I2C_InitStruct.I2C_ClockSpeed = I2c_ClockFrequency/2;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
I2C1-›CR2 |= I2C_CR2_ITBUFEN | I2C_CR2_ITEVTEN | I2C_CR2_ITERREN;
NVIC_EnableIRQ(I2C1_EV_IRQn);
NVIC_EnableIRQ(I2C1_ER_IRQn); |
Далее нам понадобится несколько рабочих переменных:
Код:
|
/* Interrupt Variables */
volatile u8 Reg, DataOKFlag = 0, I2C_Address, I2C_Reg, I2C_Mode = WRITE;
volatile u8 * I2C_Buffer, I2C_Error, I2C_DataLen; |
Ну и собственно, обработчик событий:
Код:
|
void I2C1_EV_IRQHandler (void)
{
static u8 I2C_BufferI;
if (I2C1-›SR1&I2C_SR1_SB) //START send ok
{
I2C_BufferI = 0;
I2C1-›CR1 |= I2C_CR1_ACK;
I2C1-›DR = I2C_Address;
return;
}
if (I2C1-›SR1&I2C_SR1_ADDR) //Address send ok
{
(void) I2C1-›SR2;
I2C1-›DR = I2C_Reg;
if (I2C_Mode == WRITE) return; //Mode == WRITE
if ((I2C_Address&1) == 0) //Mode == READ, writing REG
{
I2C_Address|=1;
return;
}
}
if (I2C1-›SR1&I2C_SR1_BTF) //Data send ok
{
if (I2C_Address&1) //Mode == READ
{
I2C1-›CR1 |= I2C_CR1_START;
return;
}
if (I2C_BufferI‹I2C_DataLen)
{
I2C1-›DR = I2C_Buffer[I2C_BufferI];
I2C_BufferI++;
if (I2C_BufferI == I2C_DataLen)
{
I2C1-›CR1 |= I2C_CR1_STOP;
DataOKFlag = SET;
}
}
return;
}
if (I2C1-›SR1&I2C_SR1_RXNE) //read data
{
I2C_Buffer[I2C_BufferI] = I2C1-›DR;
I2C_BufferI++;
if (I2C_BufferI == I2C_DataLen)
{
I2C1-›CR1 &= ~I2C_CR1_ACK;
I2C1-›CR1 |= I2C_CR1_STOP;
DataOKFlag = SET;
}
}
} |
И обработчик ошибок:
Код:
|
void I2C1_ER_IRQHandler (void)
{
if (I2C1-›SR1&I2C_SR1_AF) //ACK failure
{
I2C1-›SR1&=~I2C_SR1_AF; //clear IT pending bit
I2C_Error = I2c_Error_NoAck;
DataOKFlag = SET;
I2C1-›CR1 |= I2C_CR1_SWRST;
return;
}
} |
Процедура работы с одним восьмибитным регистром (под EEPROM сами переделайте).
Код:
|
void I2C1_IT_IO_DataToReg (u8 Address, u8 Reg, u8 * Data, u8 Len, u8 Mode)
{
static u16 CR2_Value = 0;
static u16 CCR_Value = 0;
static u16 TRISE_Value = 0;
if (CR2_Value == 0) CR2_Value = I2C1-›CR2;
if (CCR_Value == 0) CCR_Value = I2C1-›CCR;
if (TRISE_Value == 0) TRISE_Value = I2C1-›TRISE;
DataOKFlag = RESET;
I2C_Address = Address;
I2C_Reg = Reg;
I2C_Buffer = Data;
I2C_Error = 0;
I2C_DataLen = Len;
if (Mode) I2C_Mode = READ;
else I2C_Mode = WRITE;
if (I2C1-›CR1&I2C_CR1_SWRST) //I2C reset sequence
{
I2C1-›CR1 &= ~I2C_CR1_SWRST;
I2C1-›CR2 = CR2_Value;
I2C1-›CCR = CCR_Value;
I2C1-›TRISE = TRISE_Value;
I2C1-›CR1 |= I2C_CR1_PE;
}
I2C1-›CR1 |= I2C_CR1_START;
} |
И две публичные функции для полинга и диагностики ошибок.
Код:
|
u8 I2C1_IT_Ready (void)
{
return DataOKFlag;
}
u8 I2C1_IT_ReturnError (void)
{
return I2C_Error;
} |
Пример работы:
Код:
|
while (I2C1_IT_Ready() == RESET);
I2C1_IT_IO_DataToReg(MPU6050_DEFAULT_ADDRESS, MPU6050_RA_INT_STATUS, Buffer, sizeof(Buffer), READ); |
Где
Код:
|
#define READ 1
#define WRITE 0
#define I2c_Success 0x00
#define I2c_Error_NoAck 0x01
#define I2c_Error_Busy 0x02
#define I2c_Error_NoDataReady 0x03 |
Последний раз редактировалось Easyrider83; 17.04.2014 в 14:18.
|
|
|
Эти 3 пользователя(ей) сказали Спасибо Easyrider83 за это сообщение:
|
|
|
18.04.2014, 17:20
|
#4009
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Почему Обработчик прерывания срабатывает сразу после запуска таймера ?
Запрограммировал таймер на отчет временных интервалов:
Код:
|
/* Настройка таймера TIM2 на событие: Прерывание при совпадении с р-ром TIM2_ARR */
TIM2-›ARR=(8000); // загрузка рег-ра для сравнения 366/8000=0,046 Hz
TIM2-›PSC=(65536-1); // предделитель CK_CNT=24000000/65536=366 Hz
TIM2-›DIER|=(TIM_DIER_UIE); // разрешаем прерывание по срабатыванию таймера
TIM2-›CNT=1;
TIM2-›CR1|=(TIM_CR1_CEN); // Запуск Таймера
/* Разрешение прерывания TIM2 */
NVIC_EnableIRQ(TIM2_IRQn); |
Период србатывания ~21сек.
В обработчике поставил маркер срабатывания на PC8:
Код:
|
void TIM2_IRQHandler (void)
{
u32 i;
TIM2-›SR &=~(TIM_SR_UIF);// сброс ф.прерывания
SWITCH_PIN(PC8);
} |
Как только запускаю программу почемуто сразу срабатывает прерывание, хотя событие не наступило?
Как сделать чтобы первое срабатывание было только по совпадению с рег-ом ARR ?
|
|
|
|
20.04.2014, 20:10
|
#4010
|
Временная регистрация
Регистрация: 12.03.2005
Адрес: Москва
Сообщений: 61
Сказал спасибо: 42
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Не было печали - купила баба порося. А мужик купил STM32F3 плату. И к ней энкодер, который подключил к TIM4 (PD12 и 13). Руководствуясь Reference manual RM0316, написал следующее:
RCC-›APB1ENR |= RCC_APB1ENR_TIM4EN;//Включаем тактирование TIM4
/***** Конфигурирую порт D: PD.0 - PD.6, PD.12, PD.13 *****/
PortD -› MODER = 0x0A001555; // PD.12, PD.13 как альтернативные
PortD -› OTYPER = 0x00000000; // Пуш-пуль
PortD -› OSPEEDR = 0x00000000; // 2 МГц
PortD -› PUPDR = 0x05401555; // Подтяжка вверх
void Init_Encoder (void) // Конфиг таймера в реж. энкодера
{ NVIC_EnableIRQ (TIM4_IRQn); // Разрешить прерывание
TIM4-›CCER = TIM_CCER_CC1P | TIM_CCER_CC2P; // инвертировать входной сигнал
TIM4-›CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; // Подключить счётчик к PortD.12 и PortD.13
TIM4-›SMCR = TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1; // Счёт по фронту и спаду
TIM4 -› ARR = 0x0004; // Reload counter
TIM4 -› DIER = 1; // Разрешить прерывание
TIM4-›CR1 |= TIM_CR1_CEN; //Старт счета таймера
}
void TIM4_IRQHandler (void) // Обработка прерывания
{ TIM4-›SR &= ~TIM_SR_UIF;
........................... }
Цель - щелчок энкодера зажигает следующий LED в кругу на плате в зависимости от направления вращения. Но чудо не произошло. В дебагере (Keil) видно - счётчик TIM4_CNT не считает. Почему? Что я не доучёл?
Последний раз редактировалось sergeyye; 20.04.2014 в 23:33.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 07:19.
|
|