13.07.2011, 15:26
|
|
Гражданин KAZUS.RU
Регистрация: 12.10.2009
Сообщений: 576
Сказал спасибо: 30
Сказали Спасибо 138 раз(а) в 110 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Появились вопросы по таймерам. Как мне сделать на STM32F100 фазосдвигающий мост (имею ввиду топологию источника питания)? Там вроде бы все есть: несколько таймеров, комплементарные выходы. Но еще нужно использование входа break, потому что мой мост с поцикловым ограничением тока. Т.е. при поступлении сигнала на этот вход текщий цикл PWM должен заканчиваться. И тут возникают проблемы - у второй ноги моста состояние "выключено" меняется на противоположное каждый период. Я не понимаю как задать режим для таймеров. Это вообще возможно?
Еще в очередной раз пну этот STM. Судя по схеме клоков нельзя на переферию давать более высокий клок, чем на ядро. А у LPC - можно. Т.е. там можно выдать 10 МГц на ядро, но с PLL сделать 100 МГц для некоторй перефирии, в чатности SPI.
|
|
|
|
14.07.2011, 12:02
|
|
Частый гость
Регистрация: 18.01.2011
Сообщений: 21
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Изучаем STM32 Cortex M3
Привожу листинг. Не работает АЦП. Подскажите что делать?
PS: Остальное-рабочее( может кому пригодится).
Цитата:
|
/************************************************** ************
STM32VLDiscovery (STM32F100RB)
PA0-кнопка пользовательская
PС4-вход АЦП
PC8-светодиод синий
PC9-светодиод зеленый
LCD: (5кОм open-drain 5В)
- DB4 = PC3
- DB5 = PC2
- DB6 = PC1
- DB7 = PC0
- E = PC12
- RW = PC11
- RS = PC10 */
/************************************************** *************/
#include "stm32F10x.h"
#include "LCD.h"
/*Глобальные переменные*/
u32 tmp;
u32 statement; // Состояние программы.
u32 i=1;//Счетчик
u32 test_count;
u16 adc;
/***********************Функции инициализации********************/
uint32_t RCC_Init(void) //Инициализация системы тактирования
{
uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Конфигурацяи SYSCLK, HCLK, PCLK2 и PCLK1 */
/* Включаем HSE */
RCC-›CR |= ((uint32_t)RCC_CR_HSEON);
/* Ждем пока HSE не выставит бит готовности либо не выйдет таймаут*/
do
{
HSEStatus = RCC-›CR & RCC_CR_HSERDY;
StartUpCounter++;
}
while( (HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ( (RCC-›CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
/* Если HSE запустился нормально */
if ( HSEStatus == (uint32_t)0x01)
{
/* Включаем буфер предвыборки FLASH */
FLASH-›ACR |= FLASH_ACR_PRFTBE;
/* Конфигурируем Flash на 2 цикла ожидания */
/* Это нужно потому, что Flash не может работать на высокой частоте */
/* если это не сделать, то будет странный глюк. Проц может запуститься, но через пару */
/* секунд повисает без "видимых причин". Вот такие вот неочевидные вилы. */
FLASH-›ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH-›ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
/* AHB Prescaler = 1 */
RCC-›CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
/* APB2 Prescaler = 1 */
RCC-›CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
/* APB1 Prescaler = 2 */
RCC-›CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* Конфигурируем множитель PLL configuration: PLLCLK = HSE * 2 = 16 MHz */
/* При условии, что кварц на 8МГц! */
/* RCC_CFGR_PLLMULL2 - множитель на 2. Если нужна другая частота, не 16МГц */
/* то выбираем другой множитель. */
/* Сбрасываем в нули прежнее значение*/
RCC-›CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
/* А теперь накатываем новое */
/* RCC_CFGR_PLLSRC_HSE -- выбираем HSE на вход */
/* RCC_CFGR_PLLMULL2 -- множитель 2 */
RCC-›CFGR |= (uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL5);
/* Все настроили? Включаем PLL */
RCC-›CR |= RCC_CR_PLLON;
/* Ожидаем, пока PLL выставит бит готовности */
while((RCC-›CR & RCC_CR_PLLRDY) == 0)
{
// Ждем
}
/* Работает? Можно переключать! Выбираем PLL как источник системной частоты */
RCC-›CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC-›CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Ожидаем, пока PLL выберется как источник системной частоты */
while ((RCC-›CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x0
{
// Ждем
}
}
else
{
/* Все плохо... HSE не завелся... Чего-то с кварцем или еще что...
Надо бы както обработать эту ошибку... Если мы здесь, то мы работаем
от HSI! */
lcd_clear();
lcd_print (" HSE down ");
}
return HSEStatus;
}
void IRQs_Init(void)//Инициализация прерываний
{ /*ВНЕШНЕЕ ПРЕРЫВАНИЕ ОТ КНОПКИ*/
/*Разрешить тактирование AFIO (альтернативные функции линий
ввода-вывода), так как регистры управления мультиплексорами
находится в данном модуле */
RCC-›APB2ENR |= RCC_APB2ENR_AFIOEN;
/*Выбираем вход*/
AFIO-›EXTICR[0] &= ~0x000F; // Обнулили
AFIO-›EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA; // Записали
/*Триггер по спаду*/
EXTI-›FTSR |= EXTI_FTSR_TR0;
/*Разрешаем генерацию перывания по выбранной линии*/
EXTI-›IMR |= EXTI_IMR_MR0;
/*Устанавливаем приоритет*/
NVIC_SetPriority(EXTI0_IRQn,14);
/*Прерывание от таймера*/
/*Разрешить прохождение сигнала к таймеру Т17*/
RCC-›APB2ENR |= RCC_APB2ENR_TIM17EN;
/*Настроить предделитель*/
TIM17-›PSC = 2000 - 1;
/*Максимальное значение до которого будет считать таймер*/
TIM17-›ARR = 8- 1;
/*Разрешить генерацию события по достижению макс. значения*/
TIM17-›DIER |= TIM_DIER_UIE;
/*разрешить работу таймера и его сброс по достижению макс. значения*/
TIM17-›CR1 = TIM_CR1_CEN | TIM_CR1_ARPE;
/*установить приоритет и разрешить прерывания*/
NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, 15);
/*Разрешаем генерацию в NVIC( можно разрешить в программе позже)*/
//NVIC_EnableIRQ(EXTI0_IRQn);
//NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn);
}
void Port_Init(void)//Инициализация портов
{
/* Подаем тактовые импульсы на PA,PC*/
RCC-›APB2ENR |= RCC_APB2ENR_IOPAEN|RCC_APB2ENR_IOPCEN;
/*Настраиваем РА0 на вход*/
GPIOA-›CRL&=~GPIO_CRL_MODE0;
/*Пул-ап резисторы на РА0-можно не ставить на плате уже стоит*/
//GPIOA-CRL|=GPIO_CRL_CNF0;
/*PC8,PC9 на выход */
GPIOC-›CRH|= GPIO_CRH_MODE8|GPIO_CRH_MODE9;
/*PC8,PC9 -двухтактный выход общего назначения*/
GPIOC-›CRH &=~GPIO_CRH_CNF8;
GPIOC-›CRH &=~GPIO_CRH_CNF9;
/*PC0,PC1,PC2,PC3,PC10,PC11,PC12-на выход*/
GPIOC-›CRL|= GPIO_CRL_MODE0|GPIO_CRL_MODE1|GPIO_CRL_MODE2|GPIO_ CRL_MODE3;
GPIOC-›CRH|= GPIO_CRH_MODE10|GPIO_CRH_MODE11|GPIO_CRH_MODE12;
/*PC0,PC1,PC2,PC3,PC10,PC11,PC12-open drain*/
/*?*/ GPIOC-›CRL|= GPIO_CRL_CNF0_0|GPIO_CRL_CNF1_0|GPIO_CRL_CNF2_0|GP IO_CRL_CNF3_0;
/*?*/ GPIOC-›CRL&=~(GPIO_CRL_CNF0_1|GPIO_CRL_CNF1_1|GPIO_CRL_C NF2_1 |GPIO_CRL_CNF3_1);
/*?*/ GPIOC-›CRH|= GPIO_CRH_CNF10_0|GPIO_CRH_CNF11_0|GPIO_CRH_CNF12_0 ;
/*?*/ GPIOC-›CRH&=~(GPIO_CRH_CNF10_1|GPIO_CRH_CNF11_1|GPIO_CRH _CNF1 2_1);
/*Настраиваем РC4 на вход*/
GPIOC-›CRL&=~GPIO_CRL_MODE4;
GPIOC-›CRL&=~GPIO_CRL_CNF4;
}
void ADC_Init(void)
{
RCC-›CFGR &= ~RCC_CFGR_ADCPRE; //Обнулили прескейлеры
RCC-›CFGR |= RCC_CFGR_ADCPRE_DIV2; // Минимальное деление на 2
RCC-›APB2ENR |= RCC_APB2ENR_ADC1EN; //Подали тактовые импульсы на АЦП
ADC1-›SQR3|= ADC_SQR3_SQ1_2|ADC_SQR3_SQ1_4 ; // Наш 14 канал АЦП будет обрабатываться первым
ADC1-›CR2 |= ADC_CR2_EXTSEL; // запуск преобразования по установки бита swstart (или можно как закоментировано ниже)
//ADC1-›CR2 = ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2| ADC_CR2_EXTTRIG;
ADC1-›CR2 |= ADC_CR2_EXTTRIG; // включаем запуск от внешнего события (у нас это свтарт)
ADC1-›SMPR1 |= ADC_SMPR1_SMP14; // ставлю макс. кол-во циклов (239.5) на преобразование для 16 канала где теп. сенсор
ADC1-›CR2 |= ADC_CR2_ADON;
ADC1-›CR2 |= ADC_CR2_RSTCAL;
while ((ADC1-›CR2 & ADC_CR2_RSTCAL) == ADC_CR2_RSTCAL)
{
}
ADC1-›CR2 |= ADC_CR2_CAL;
while ((ADC1-›CR2 & ADC_CR2_RSTCAL) == ADC_CR2_CAL)
{
}
}
void InitAll(void)//Общая инициализация
{
RCC_Init();
Port_Init();
IRQs_Init();
ADC_Init();
}
/********************************Главная функция*************************************/
int main(void)
{
InitAll();
lcd_init();
lcd_clear();
lcd_print (" Hello ");
set_cursor (0, 1);
lcd_print (" ????????");
while(statement‹3) // Мигание светодиодами .
{
tmp=500000; while (tmp) {tmp--;} // Задержка.
GPIOC-›BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9; // Зажечь LED4, потушить LED3.
tmp=500000; while (tmp) {tmp--;} // Задержка.
GPIOC-›BSRR=GPIO_BSRR_BS9|GPIO_BSRR_BR8; // Зажечь LED3, потушить LED4.
statement++;
}
if (statement==3) // Отмигали- делаем что-нить
{ /*Разрешаем генерацию в NVIC*/
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn);
while(1)
{
/*ОСНОВНОЙ ЦИКЛ*/
}
}
}
/********************************Вспомогательные функции*****************************/
void Delay( unsigned int Val) // Задержка по-тупому
{
for( ; Val != 0; Val--)
{
__NOP();
}
}
/* Функция из числа возвращает указательна строку из числа-
применяем для получения символов некоторых значений*/
char* itoa(int val, int base)
{
static char buf[32] = {0};
int i = 30;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
return &buf[i+1];
}
/************************** ПРЕРЫВАНИЯ *******************************************/
/* Внешнее прерывание от кнопки */
void EXTI0_IRQHandler(void)
{
GPIOA-›BSRR=GPIO_BSRR_BR8;
if(EXTI-›PR & EXTI_PR_PR0)
{
EXTI-›PR|=EXTI_PR_PR0;
}
NVIC_ClearPendingIRQ(EXTI0_IRQn);
GPIOC-›BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BS9;
lcd_clear();
lcd_print (" Thank you ");
i++;
Delay(10000000);
}
/* Прерывание от таймера*/
void TIM1_TRG_COM_TIM17_IRQHandler()
{
if(test_count==0)
{
GPIOC-›BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9;
}
if(test_count==(10000*i))
{
GPIOC-›BSRR=GPIO_BSRR_BR8|GPIO_BSRR_BS9;
}
if(++test_count›(20000*i))
{
test_count=0;
ADC1-›CR2 |= ADC_CR2_SWSTART;
while ((ADC1-›SR & ADC_SR_EOC) != ADC_SR_EOC)
{
}
/******************************ПРОБЛЕМА************ ***********/
/*Если смотреть в отладчике, то во-первых на ADC1-›DR нули , но это не все.
Он откуда-то резко после этого шага присваивает значение adc какое-то рандомное.
Настораживает асемблерный код , соответствующий данной строке:
0x08000B7E 4815 LDR r0,[pc,#84] ; @0x08000BD4
0x08000B80 6800 LDR r0,[r0,#0x00]
0x08000B82 4915 LDR r1,[pc,#84] ; @0x08000BD8
0x08000B84 6008 STR r0,[r1,#0x00]
************************************************** *************/
adc = ADC1_DR;
lcd_clear();
lcd_print (itoa(adc,10));}
}
|
Последний раз редактировалось ^smbd^; 14.07.2011 в 12:07.
|
|
|
|
14.07.2011, 13:55
|
|
Гражданин KAZUS.RU
Регистрация: 12.10.2009
Сообщений: 576
Сказал спасибо: 30
Сказали Спасибо 138 раз(а) в 110 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Для начала надо получить рабочий АЦП в НОРМАЛЬОМ режиме, то есть включив непрерывную оцифровку и считывая результаты в собственном прерывании АЦП.
Далее в строке while ((ADC1-›SR & ADC_SR_EOC) != ADC_SR_EOC) { }
Сразу 2 косяка. Во-первых, условие пишется как while (!(ADC1-›SR & ADC_SR_EOC))
Во-вторых, с чего вдруг компилятор станет исполнять пустой цикл? Если компилятор тупой, то может прокатить. Но GCC, к примеру, выкидывает такой цикл полностью. Потому что он пустой. Чтоб не выкидывал, надо внутрь __NOP() ставить, или аналог.
|
|
|
|
14.07.2011, 14:13
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Помогите начать работать либо с кеил, либо с иар. Как генерить hex и запускать в протеусе я научился на готовых примерах из IAR. Но как начать новый проект? Откуда взять main.c? Как сгенерить начальную инициализацию? Как-то туго идет с этими АРМами. С пиками, авр-ами за 15 минут осваиваешь как ногами дрыгать и через неделю уже прогу с пятью модулями пишешь.
Вынужден перейти на АРМ по экономическим соображениям.
|
|
|
|
14.07.2011, 14:50
|
|
Частый гость
Регистрация: 18.01.2011
Сообщений: 21
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Изучаем STM32 Cortex M3
Сообщение от Easyrider83
|
Помогите начать работать либо с кеил, либо с иар. Как генерить hex и запускать в протеусе я научился на готовых примерах из IAR. Но как начать новый проект? Откуда взять main.c? Как сгенерить начальную инициализацию? Как-то туго идет с этими АРМами. С пиками, авр-ами за 15 минут осваиваешь как ногами дрыгать и через неделю уже прогу с пятью модулями пишешь.
Вынужден перейти на АРМ по экономическим соображениям.
|
http://easyelectronics.ru/category/arm-uchebnyj-kurs
|
|
|
|
14.07.2011, 15:09
|
|
Частый гость
Регистрация: 18.01.2011
Сообщений: 21
Сказал спасибо: 5
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Изучаем STM32 Cortex M3
Сообщение от tanq
|
Для начала надо получить рабочий АЦП в НОРМАЛЬОМ режиме, то есть включив непрерывную оцифровку и считывая результаты в собственном прерывании АЦП.
Далее в строке while ((ADC1-›SR & ADC_SR_EOC) != ADC_SR_EOC) { }
Сразу 2 косяка. Во-первых, условие пишется как while (!(ADC1-›SR & ADC_SR_EOC))
Во-вторых, с чего вдруг компилятор станет исполнять пустой цикл? Если компилятор тупой, то может прокатить. Но GCC, к примеру, выкидывает такой цикл полностью. Потому что он пустой. Чтоб не выкидывал, надо внутрь __NOP() ставить, или аналог.
|
Я понимаю , что с постоянным сбором- хорошо и православно, но частенько нужна бывает и по событию обработка , а она не фурычит.Кстати, до сих пор не фурычит и с исправленным циклом:
Цитата:
|
while (!(ADC1-›SR & ADC_SR_EOC))
{
__NOP();
}
|
|
|
|
|
14.07.2011, 15:27
|
|
Гражданин KAZUS.RU
Регистрация: 12.10.2009
Сообщений: 576
Сказал спасибо: 30
Сказали Спасибо 138 раз(а) в 110 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Вот чтобы разобраться что именно не работает, я и рекомендую запустить сначала боле простой вариант. Он то работает, или тоже нет?
|
|
|
|
14.07.2011, 16:32
|
|
Частый гость
Регистрация: 20.03.2010
Сообщений: 27
Сказал спасибо: 10
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от tanq
|
Вот чтобы разобраться что именно не работает, я и рекомендую запустить сначала боле простой вариант. Он то работает, или тоже нет?
|
Я с этого начал, ибо пример был)
Завтра попробую обычный.
А тут АЦП не надо как-нить ремапом включить? Я чет не нашел как и решил , что не надо , но не работает...
Последний раз редактировалось <smbd>; 14.07.2011 в 16:41.
|
|
|
|
14.07.2011, 17:18
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Ой тяжко дело двигается... Сколько надо создать проектов, чтобы уже не залезать в интернет для поиска статьи как руководства к действиям? Это ж план на пол сотни пунктов.
|
|
|
|
14.07.2011, 19:21
|
|
Частый гость
Регистрация: 20.03.2010
Сообщений: 27
Сказал спасибо: 10
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
|
Re: Изучаем STM32 Cortex M3
Сообщение от Easyrider83
|
Ой тяжко дело двигается... Сколько надо создать проектов, чтобы уже не залезать в интернет для поиска статьи как руководства к действиям? Это ж план на пол сотни пунктов.
|
Да не много. Я еще ниче хорошего не сделал , но проект создаю уже без подсказок. Дискавери, кстати, мне понравился весьма. За свои деньги( а многим нахаляву)- отлично просто. Щас новый вариант дискавери вышел на другом камне , с мониторчиком мелким и емкостными кнопками- наверно потом тоже куплю.
Последний раз редактировалось <smbd>; 14.07.2011 в 19:33.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:01.
|
|