STM32VLDISCOVERY - изучение периферии

Летний выезд на периферию или курс жесткого выживания на Atollic. Часть2.
Так, с Атолликом вроде разобрались. Теперь собственно надо бы занятся периферией. Так как выживание жесткое, то пришлось использовать то что есть, а именно саму плату Stm32vldiscovery и компьютер, больше ничего под руками у меня не было, топор и лопата не подошли (. Единственно что было на плате это пара кнопок и пара светодиодов, но как оказалось для начала этого вполне достаточно. Да, так как я еще не отвык от ассемблера я записывал в регистры значения в хексах, но всегда рядом записано как это принято в си.
Пример классический — жатие на кнопку и переключение светодиодов:
#include "stm32f10x.h"
int main(void)
{
//	 RCC->APB2ENR=0x00000014;
	 RCC->APB2ENR|=RCC_APB2ENR_IOPAEN; // enable port A
	 RCC->APB2ENR|=RCC_APB2ENR_IOPCEN; // enable port C

//	 GPIOC->CRH=0x00000011;		   //push/pull на С выводы 8, 9
	 GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;
while(1)
  {
         if(!((GPIOA->IDR)&0x00000001))
           {
	   GPIOC->ODR=0x00000100;          //восьмой - зеленый
           }
            else
                {
                 GPIOC->ODR=0x00000200;    // девятый синий
                 }
  }
}


тут сразу начались чудеса — нормально т.е. вот так:

GPIOC->CRH |= GPIO_CRH_MODE8_0;
GPIOC->CRH |= GPIO_CRH_MODE9_0;

порт инициализироваться ну никак не хотел. Глубинное бурение показало что по вкючении в CRH и так уже есть какая-то хрень(там должна быть умолчальная конфигурация input float — спасибо hellraiser (и см. коментарии) прим. basil) это следовало из того что, что при вырезании того что должно быть такой же бит маской, все начинало работать:
GPIOC->CRH &= 0x00000011;
или предварительно регистр обнулить — GPIOC->CRH = 0; тогда все инициализировалось штатно.
Пример второй запузыриваем таймер.
#include "stm32f10x.h"
int r=0;// это флаг
 	 	 void TIM2_IRQHandler (void)
	       {
		TIM2->CR1=0x0000;		//  не enable(бит0)
//		TIM2->CR1 &=~TIM_CR1_CEN;
		TIM2->SR=TIM2->SR & 0xFFFE;	//В status reg обнуляем нулевой бит - UIF
//		TIM2->SR&=~TIM_SR_UIF;
		if (r==1) { r=2; GPIOC->ODR=0x00000100; //восьмой - зеленый
		     	   }
		   else { r=1; GPIOC->ODR=0x00000200; 	 /*девятый - синий*/
			}
		TIM2->CNT=0x7530;		// от чего считаем
		TIM2->CR1=0x0001;		//  enable(бит0)
//		TIM2->CR1|=TIM_CR1_CEN;
	        }

int main(void)
{
		__enable_irq();         	// общее включение прерывания
		NVIC_EnableIRQ(TIM2_IRQn);	//прерывание второго таймера - обработчик
		RCC->APB1ENR=0x00000001;	// таймер2 enable
//		RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
		RCC->APB2ENR=0x00000010;	// порт C enable
//		RCC->APB2ENR|=RCC_APB2ENR_IOPCEN;
		GPIOC->CRH=0x00000011;		// 8--ой и 9-й оба на выход push/pull
//		GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;

		TIM2->CNT=0x7530;		// предв знач  счит с него до 65535
		TIM2->PSC=0x00E4;		//228 предделитель
		TIM2->DIER=0x0001;		//прер по переполнен UIE
//		TIM2->DIER|=TIM_DIER_UIE;
		TIM2->CR1=0x0001;		// запуск таймера
//		TIM2->CR1|=TIM_CR1_CEN;
int i;
  while (1)
  {
	i++;

  }
}

тут единственно что необычно это то что надо самому сбрасывать флаг. Классическое прерывание при переполнении счетчика, мигает то один то другой диод в зависимости от значения флага которое тоже потом меняется.
В принципе вот еще почти тоже самое но на другом прерывании, было переполнение а сейчас сравнение, и счет до указанного значения (TIM2->ARR):
#include "stm32f10x.h"
int r=0;// - флаг
		   void TIM2_IRQHandler (void)
		{
		TIM2->CR1=TIM2 ->CR1 & 0xFFFE;//таймер не enable(бит0)
//		TIM2->CR1 &=~TIM_CR1_CEN;
		TIM2->SR=TIM2->SR & 0xFFFD;   //В status reg обнуляем второй  бит - 1 - OCR1
//		TIM2->SR&=~TIM_SR_CC1IF;
		if (r==1) { r=2; GPIOC->ODR=0x00000100; //восьмой - зеленый
			  }
		   else { r=1; GPIOC->ODR=0x00000200; /*девятый - синий*/
		   	 }
       	        TIM2->CR1=TIM2->CR1 | 0x0001; //таймер enable(бит0)
//	        TIM2->CR1|=TIM_CR1_CEN;
		}

int main(void)
{
		__enable_irq();                 // общее включение прерывания
		NVIC_EnableIRQ(TIM2_IRQn);



		RCC->APB1ENR=0x00000001;	// таймер2 enable
//		RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
		RCC->APB2ENR=0x00000010;	// порт C enable
//		RCC->APB2ENR|=RCC_APB2ENR_IOPCEN;
		GPIOC->CRH=0x00000011;		// 8--ой и 9-й оба на выход push/pull
//		GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;

		TIM2->PSC=0x00E4;		//228 предделитель
		TIM2->DIER=0x0002;		//прер по сравн первый канал бит - CC1IE
//		TIM2->DIER |= TIM_DIER_CC1IE;
		TIM2->CCR1=0x7000;		//уровень сравнения - когда возн прер по сравн
		TIM2->ARR= 0x7530;		//auto reload reg -  до чего считаем ( вершина )
		TIM2->CR1=0x00E1;		// таймер  enable(бит0) напр счета  от 0 (бит4 DIR если 1 к 0)0, 
                                                //ARPE бит enable граница до кот счет бит 7 в 1 -( т е 8)
						// 6-5-биты CMS-center align mode-туда-сюда -(11)
//		TIM2->CR1|=TIM_CR1_CMS;
//		TIM2->CR1|=TIM_CR1_ARPE;
//		TIM2->CR1|=TIM_CR1_CEN;
int i = 0;

  while (1)
  {
	i++;

  }
}

тут любопытного то, как начинает переползать длительность с одного светодиода на другой при изменении TIM2->CCR1 скажем от 0х0500 и до 0х7000.
Ну и интересно попробовать ШИМ тут я попробовал мягко помигать светодиодами:
#include "stm32f10x.h"
int s=0;// - флаг
		   void TIM2_IRQHandler (void)
		{
		TIM2->CR1=TIM2 ->CR1 & 0xFFFE;	//таймер не enable(бит0)
//     	        TIM2->CR1 &=~TIM_CR1_CEN;
		TIM2->SR=TIM2->SR & 0xFFFD;	//В status reg обнуляем второй  бит - 1 - OCR1
//		TIM2->SR&=~TIM_SR_CC1IF;
		if (s==1) { s=2; GPIOC->ODR=0x00000000;
			   }
		     else { s=1; GPIOC->ODR=0x00000300;   // плавно мерцают оба
			        }
		if  ((TIM2->CCR1) < 0x8400 ) {(TIM2->CCR1)=(TIM2->CCR1) + 0x007F;}
		     else {(TIM2->CCR1) = 0x007F ;}
	        if  ((TIM2->CR1) & 0x0010 ) {(TIM2->CNT)=(TIM2->CNT) + 0x007F ;}// коррекция значения 
                                                          //счетчика чтобы не перескакивать сравнение
		     else {(TIM2->CNT) = (TIM2->CNT)+ 0x007F ;}
		TIM2->CR1=TIM2->CR1 | 0x0001;	          //таймер enable(бит0)
//		TIM2->CR1|=TIM_CR1_CEN;

		}
int main(void)
{
	        __enable_irq();                 // общее включение прерывания
	        NVIC_EnableIRQ(TIM2_IRQn);

		RCC->APB1ENR=0x00000001;	// таймер2 enable
//		RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
		RCC->APB2ENR=0x00000010;	// порт C enable
//		RCC->APB2ENR|=RCC_APB2ENR_IOPCEN;
		GPIOC->CRH=0x00000011;		// 8--ой и 9-й оба на выход push/pull
//		GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;

		TIM2->PSC=0x0001;		// предделитель
		TIM2->DIER=0x0002;		//прер по сравн первый канал бит - CC1IE
//		TIM2->DIER |= TIM_DIER_CC1IE;
		TIM2->CCR1=0x4000;		//уровень сравнения - когда возн прер по сравн
		TIM2->ARR= 0x8550;		//auto reload reg -  до чего считаем ( вершина )
		TIM2->CR1=0x00E1;		// таймер  enable(бит0) напр счета  от 0 (бит4 DIR если 1 к 0)0, 
                                                //ARPE бит enable граница до кот счет бит 7 в 1 -( т е 8)
						// 6-5-биты CMS-center align mode-туда-сюда -(11)
//		TIM2->CR1|=TIM_CR1_CMS;
//		TIM2->CR1|=TIM_CR1_ARPE;
//		TIM2->CR1|=TIM_CR1_CEN;
int i = 0;

  while (1)
  {
	i++;

  }
}

получилось и правда неплохо(ну прям science fiction -) ). В прерывании по сравнению увеличивается и значение
самой границы. Тут затык был чтобы допереть, что надо при передвигании границы, при которой возникает прерывание сравнения, скорректировать и значение счетчика, а то можно пролететь мимо следующего прерывания.

Таймеры могут синронизироваться друг от друга:
#include "stm32f10x.h"
int r=0;
int s=0;

		     void TIM1_UP_TIM16_IRQHandler (void)
		   {
		   TIM1->CR1=TIM1 ->CR1 & 0xFFFE;	// не enable(бит0)
//		   TIM1->CR1 &=~TIM_CR1_CEN;
		   TIM1->SR=TIM1->SR & 0xFFFE;		//В status reg обнуляем   бит - 0 - UIF
//		   TIM1->SR&=~TIM_SR_UIF;
		   if (s==1) { s=2; GPIOC->ODR=GPIOC->ODR & 0xFFFFFDFF;
			     }

		       else { s=1; GPIOC->ODR=GPIOC->ODR | 0x00000200;
			    }
		    TIM1->CR1=TIM1->CR1 | 0x0001;	//enable(бит0)
//		    TIM1->CR1 |= TIM_CR1_CEN;
		   }
		     void TIM2_IRQHandler (void)
		   {
		    TIM2->CR1=TIM2 ->CR1 & 0xFFFE;	// не enable(бит0)
//		    TIM2->CR1 &=~TIM_CR1_CEN;
		    TIM2->SR=TIM2->SR & 0xFFFE;		//В status reg обнуляем второй  бит - 0 - UIF
//		    TIM2->SR &=~ TIM_SR_UIF;
		    if (r==1) { r=2; GPIOC->ODR=GPIOC->ODR & 0xFFFFFEFF;
			       }
			else { r=1; GPIOC->ODR=GPIOC->ODR | 0x00000100;
			     }
		    TIM2->CR1=TIM2->CR1 | 0x0001;	//enable(бит0)
//		    TIM2->CR1 |= TIM_CR1_CEN;
		   }
int main(void)
{
		__enable_irq();                         // тотальное включение прерывания
		NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn );
		NVIC_EnableIRQ(TIM2_IRQn);

		RCC->APB1ENR=0x00000001;	        // таймер2 enable
//		RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
		RCC->APB2ENR=0x00000810;	        // таймер 1 enable , порт C enable
//		RCC->APB2ENR|=RCC_APB2ENR_IOPCEN;
//		RCC->APB2ENR|=RCC_APB2ENR_TIM1EN;
		GPIOC->CRH=0x00000011;		        // 8--ой и 9-й оба на выход push/pull
//		GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;
		// TIMER_2

//master
		TIM2->CR2=0x0020;			// master timer update mode mms - 010;
//		TIM2->CR2|=TIM_CR2_MMS_1;
//
		TIM2->PSC=0x0FFF;			// предделитель
		TIM2->DIER=0x0001;			//прер по переполн
//		TIM2->DIER |= TIM_DIER_UIE;
		TIM2->ARR= 0x01E8;			// -  до чего считаем ( вершина )

		// TIMER_1

//slave
		TIM1->SMCR=0x0017;    			//external clock mode sms - 111, 
                                                        //TS для таймера 1 по таблице синхр от таймера 2 - 001
//		TIM1->SMCR|=TIM_SMCR_SMS;
//		TIM1->SMCR|=TIM_SMCR_TS_0;
//
		TIM1->PSC=0x0001;			//предделитель
		TIM1->DIER=0x0001;			//прер по переполн
//		TIM1->DIER |= TIM_DIER_UIE;
		TIM1->ARR= 0x0008;			// -  до чего считаем ( вершина )

// запуск

		TIM1->CR1=0x0081;			// тайм1 enable(бит0), ARPE бит enable 
                                                        //граница до кот счет бит 7 в 1 -( т е 8)
//		TIM1->CR1|=TIM_CR1_ARPE;
//		TIM1->CR1|=TIM_CR1_CEN;
		TIM2->CR1=0x0081;			// тайм2 enable(бит0) , ARPE бит enable      
                                                        //граница до кот счет бит 7 в 1 -( т е 8)
//		TIM2->CR1|=TIM_CR1_ARPE;
//		TIM2->CR1|=TIM_CR1_CEN;

int i = 0;

  while (1)
  {
	i++;

  }
}

slave использует в качестве входного сигналы с мастера, каждый таймер мигает своим диодом. Можно делать цепочки из тактирующих друг друга таймеров, средние звенья надо поставить и мастером и слугой.

Пример с ДМА — тут вариант два в одном, на прерываниях и без:
#include "stm32f10x.h"
long int s=0x00000200;
long int r=0x00000100;

//	         void TIM1_CC_IRQHandler (void)
//	       {
//
//	       TIM1->CR1=TIM1 ->CR1 & 0xFFFE;			// счет не enable(бит0)
//	       if (TIM1->SR & TIM_SR_CC1IF){(TIM1->SR)=(TIM1->SR) &(~TIM_SR_CC1IF);GPIOC->ODR=s;}
//		   else{TIM1->SR=(TIM1->SR) &(~TIM_SR_CC4IF);GPIOC->ODR=r;}
//	       TIM1->CR1=TIM1->CR1 | 0x0001;			// счет enable(бит0)
//		}

int main(void)
{
//		__enable_irq();                 // общее включение прерывания
//		NVIC_EnableIRQ(TIM1_CC_IRQn );
		RCC->APB2ENR=0x00000810;	//порт C enable tacting -1 , 8 - таймер 1 enable tacting 
                                                //!!! тактирование до конфигурирования !!!
//		GPIOC->CRH=0x00000011;		// 8--ой и 9-й оба на выход push/pull
		GPIOC->CRH = GPIO_CRH_MODE8_0 | GPIO_CRH_MODE9_0;


		TIM1->PSC=0x00E4;		// предделитель
//		TIM1->DIER=0x1200;		//запрос 4,1  каналов DMA биты - CC4DE и CC2DE,
                                                //а так  без дма 0x0012 - CC1IE и CC4IE
		TIM1->DIER |= TIM_DIER_CC1DE;
		TIM1->DIER |= TIM_DIER_CC4DE;
//		TIM1->DIER |= TIM_DIER_CC1IE;
//		TIM1->DIER |= TIM_DIER_CC4IE;


		TIM1->CCR1=0x5000;			//уровень сравнения - когда возн прер по сравн
		TIM1->CCR4=0x0500;			//уровень сравнения - когда возн прер по сравн
		TIM1->ARR= 0x7530;			//auto reload reg -  до чего считаем ( вершина )
//		TIM1->CR1=0x00C1;			// прер enable(бит0)ж напр счета  от 0 (бит4 DIR если 1 к 0)0,
                                                        //ARPE бит enable граница до кот счет бит 7 в 1 -( т е 8)
							// 6-5-биты CMS-center align mode-туда-сюда -(11)
		TIM1->CR1 |= TIM_CR1_ARPE;
		TIM1->CR1 |= TIM_CR1_CMS_1;
		TIM1->CR1 |= TIM_CR1_CEN;

		// DMA
		RCC->AHBENR |=RCC_AHBENR_DMA1EN; 		//DMA 1 enable
		DMA1_Channel2->CPAR =(uint32_t)&GPIOC->ODR;	// адрес порта выхода
		DMA1_Channel2->CMAR=(uint32_t)&r;		//адрес переменной
		DMA1_Channel2->CNDTR=0x00000001;		//количество пересылок данных
		DMA1_Channel2->CCR |=DMA_CCR2_DIR;		//направление пересылки из памяти по ум  с периферии
		DMA1_Channel2->CCR |= DMA_CCR2_CIRC;		//непрерывно
		DMA1_Channel2->CCR |= DMA_CCR2_MSIZE_1; 	// 32 bit
		DMA1_Channel2->CCR |= DMA_CCR2_PSIZE_1;		// 32 bit
		DMA1_Channel4->CPAR =(uint32_t)&GPIOC->ODR;
		DMA1_Channel4->CMAR=(uint32_t)&s;
		DMA1_Channel4->CNDTR=0x00000001;
		DMA1_Channel4->CCR |=DMA_CCR4_DIR;
		DMA1_Channel4->CCR |= DMA_CCR4_CIRC;
		DMA1_Channel4->CCR |= DMA_CCR4_MSIZE_1;
		DMA1_Channel4->CCR |= DMA_CCR4_PSIZE_1;
		DMA1_Channel2->CCR |= DMA_CCR2_EN;	        //вкл
		DMA1_Channel4->CCR |= DMA_CCR4_EN;	        //вкл
//		DMA1_Channel2->CCR = 0x00000A31;
//		DMA1_Channel4->CCR = 0x00000A31;
int i = 0;

  while (1)
  {
	i++;

  }
}

То есть таймер работает, и при наступлении события по сравнению вызывает канал ДМА который передает значение из памяти в регистр ввода-вывода. Один канал передает одно число, второй — второе, соответственно горит то один то другой диод. Чтобы сделать на прерываниях надо просто закоментировать DMA 1 enable и раскоментировать хэндлер и прерывания по сравнению.
Так, UART и ремап — тут мысль в том, что таймер на прерывании шлет то одно то другое число (211 и 110 от балды оба)- пихает в DR и, по прерыванию передачи и приема каждый UART мигает своим диодом (один по передаче второй по чтению). Тут я хотел проверить, не мешают ли друг другу каналы таймера 1 и UARTы сидящие с ними на одних пинах оказалось — нет. Более того, необязательно включать и альтернативные функции если не используется ремап, так как эти альтернативные функции дефолтные и надо просто сконфигурировать вывод и включить что надо. Для организации канала связи нужен семисантиметровый кусок провода(обычный электрический многожильный пойдет), напихиваем его на соответствующие выводы платы (Tx(PB10)->Rx(PA10) и Rx(PB11)->Tx(PA9)) включаем — работает. Потом для ремапа включаем альтернативные функции, конфигурируем соответствующие порты (раскоментируем) включаем ремап уартов и перебрасываем провод (Tx(PC10)->Rx(PB7) и Rx(PC11)->Tx(PB6)) — работает тоже ). Отдельно надо сказать про настройку скорости, необычно что десятые доли считаются отдельно, но потом когда почитаешь примеры оказывается просто. Десятые умножаются на 16 и пихаются в DIV_Fraction если влезло не все то мантисса увеличивается на один(для 115.2 кбит/с по табл частота 8 МГц, oversampling 16 — USART_BRR=4.3125 мантисса — 4 остаток 0.3125 умн на 16 остаток и округляем получается 5). Хотя посчитал-то правильно тут это не критично главное чтобы было одинаково для обоих уартов.
#include "stm32f10x.h"
int s=0;
int r=0;

		   void TIM1_UP_TIM16_IRQHandler (void)
		{
		TIM1->CR1 &=~TIM_CR1_CEN;		// не enable(бит0)
		TIM1->SR&=~TIM_SR_UIF;			//В status reg обнуляем   бит - 0 - UIF
		if (s==1) { s=2; USART1->DR=211;
			   }
		    else { s=1; USART1->DR=110;
			 }

		TIM1->CR1|=TIM_CR1_CEN;			//enable(бит0)
		}
		   void USART3_IRQHandler (void)
		{
		if (USART3->DR==211) { GPIOC->ODR=GPIOC->ODR & ~0x00000200;
			   	     }
		    else {GPIOC->ODR=GPIOC->ODR | 0x00000200;
			  }
		 }
		   void USART1_IRQHandler (void)
		{
		USART1->SR=USART1->SR & ~USART_SR_TC;
		if (r==1) { r=2; GPIOC->ODR=GPIOC->ODR & ~0x00000100;
			   }
		     else { r=1; GPIOC->ODR=GPIOC->ODR|0x00000100;
			  }
		 }
int main(void)
{
		__enable_irq();                   // общее включение прерывания
		NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn );
		NVIC_EnableIRQ(USART1_IRQn);
		NVIC_EnableIRQ(USART3_IRQn);
//порт C enable tacting  ,таймер 1 enable tacting  USART1, ports B,A 
// и AFIOEN тактирование до конфигурирования !!!
		RCC->APB2ENR |=RCC_APB2ENR_USART1EN;
		RCC->APB2ENR |=RCC_APB2ENR_TIM1EN;
		RCC->APB2ENR |=RCC_APB2ENR_IOPCEN;
		RCC->APB2ENR |=RCC_APB2ENR_IOPBEN;
//		RCC->APB2ENR |=RCC_APB2ENR_IOPAEN;//при alternate  не нужен
//alternate
		RCC->APB2ENR |=RCC_APB2ENR_AFIOEN;//выкл
		AFIO->MAPR 	|=AFIO_MAPR_USART3_REMAP_PARTIALREMAP;
		AFIO->MAPR 	|=AFIO_MAPR_USART1_REMAP;
// USART 3 enable tacting, tim-2
		RCC->APB1ENR |=RCC_APB1ENR_USART3EN;
		RCC->APB1ENR |=RCC_APB1ENR_TIM2EN;
		GPIOC->CRH=0x0000EB11;		  //C - leds  8--ой и 9-й оба на выход push/pull 10,11 Tx,Rx
//		GPIOA->CRH=0x00000EB0;		  //alternate Tx-9 pin Rx-10 //при alternate  не нужен
		GPIOB->CRL=0xEB000000;		  //alternate Tx-6 pin Rx-7
		USART1->BRR=(4<<4)+0x5;		  //115.2kB/s
		USART3->BRR=(4<<4)+0x5;		  //115.2kB/s
		USART1->CR1|=USART_CR1_UE;	  //вкл
		USART1->CR1|=USART_CR1_TCIE;      //прер по передаче
		USART1->CR1|=USART_CR1_TE;	  //разр передачи
		USART3->CR1|=USART_CR1_UE;	  //вкл
		USART3->CR1|=USART_CR1_RXNEIE;    //прерывание по приему
		USART3->CR1|=USART_CR1_RE;	  //разрешить прием
// TIMER_1

		TIM1->PSC=0x0FFF;		//делитель
		TIM1->DIER |= TIM_DIER_UIE;	//прер по переп
		TIM1->ARR= 0x01E8;		// auto reload reg -  до чего считаем ( вершина )
		TIM1->CR1|=TIM_CR1_ARPE;
		TIM1->CR1|=TIM_CR1_CEN;		//  enable(бит0), ARPE бит enable граница до кот счет бит 7

// enable


int i = 0;

  while (1)
  {
	i++;

  }
}

Ну и наконец АЦП тут короче такая вещь, когда сигнал с термодатчика доходит до нижней границы аналогового вачдога — прерывание, в котором граница смещается вниз (да, долго до меня доходило что сигнал с термодатчика падает при нагревании -) ), и диоды мигают по очереди. В принципе если греть пальцем то мигать уже начинает, и очень часто если сантиметрах в 7-5 зажигалкой (смотрите не спалите). Что интересно ADON надо включать два раза первый подается питание, второй — начинает работать.
#include "stm32f10x.h"
long int s=0x00000200;
long int r=0x00000100;
int t=0;
                 void ADC1_IRQHandler (void)
               {
	       ADC1->SR &= ~ADC_SR_AWD;
	       if (t==1) { t=2; GPIOC->ODR=0x00000100; 	//восьмой - зеленый
	   	   	 }
	   	   else { t=1; GPIOC->ODR=0x00000200; /*девятый - синий*/
	   	   	}
	        ADC1->LTR=(ADC1->DR) - 0x00000005;	//коррекция границы собаки
                }



int main(void)
{
		__enable_irq();
		NVIC_EnableIRQ(ADC1_IRQn);
		RCC->APB2ENR |=RCC_APB2ENR_IOPCEN;		//порт C enable ,ADC - enable.
		RCC->APB2ENR |=RCC_APB2ENR_ADC1EN;
		GPIOC->CRH=0x00000011;				// 8--ой и 9-й оба на выход push/pull
//		GPIOC->CRH = GPIO_CRH_MODE8_0|GPIO_CRH_MODE9_0;
		//ADC
		ADC1->CR2 |=ADC_CR2_ADON;			//ADON оказывается надо включать 2 раза
		ADC1->CR2 |= ADC_CR2_TSVREFE;			//термодатчик и опорное напр вкл
		ADC1->SQR3 = ADC_SQR3_SQ1_4;			//16-й канал идет первым в последовательности
                                                                //регулярных(и единственным)
		ADC1->SMPR1 |= ADC_SMPR1_SMP16;		        // время преобразования max
		ADC1->CR2 |=ADC_CR2_CAL;			//калибровка
		ADC1->CR2 |=ADC_CR2_CONT;			//непрерывное преобразование
		ADC1->CR1 |=ADC_CR1_AWDEN;			//аналоговая собака на регулярных каналах
		ADC1->CR1 |=ADC_CR1_AWDIE;			//прерывание от собаки
		ADC1->CR1 |=ADC_CR1_AWDCH_4;			//собака на 16 канале
		ADC1->CR2 |=ADC_CR2_ADON;			//включили АЦП
		ADC1->LTR=(ADC1->DR) - 0x00000005;		//в нижнюю границу собаки текущее значение 
                                                                //температуры с коррекцией
							        //чтобы прерывание сразу не наступило


int i = 0;

  while (1)
  {
	i++;

  }
}


Конечно приведенные небольшие примеры вовсе не исчерпывают всю периферию, но для начала чтобы познакомится с вопросом с минимальными материальными затратами пойдут. Очень интересно про периферию есть еще например у hellraiser — we.easyelectronics.ru/STM32/stm32-primery-koda.html.
  • +2
  • 30 сентября 2011, 01:02
  • basil

Комментарии (7)

RSS свернуть / развернуть
Глубинное бурение показало что по вкючении в CRH и так уже есть какая-то хрень
Там установлены биты CNFy_0, по умолчанию порт работает как вход, установив бит MODEy_0 вы перевели его на выход с открытым коллектором, а сбросив бит CNFy_0 в выход пуш-пул.
0
Да-да, в самом деле немного я тут протупил, действительно умолчально он весь должен бить забит четверками. Когда я смотрел в STMstudio содержимое регистров, не переключил на хекс представление и она мне вывалила в десятичном. Но все-таки, если верить этой студии вот например в умолчальном CRH порта А все равно какие-то восьмерки, чтобы не быть голословным: GPIOA->CRH=44448488 (хотел впихнуть картинку но тут вроде этого нельзя)
0
В Ваших примерах часто приходится видеть конструкцию такого вида:

int main(void)
{
................
int i;
  while (1)
  {
        i++;

  }
}


В действительности переменная i нигде не задействована, поэтому лучше было бы написать попроще:

int main(void)
{
................
  while (1)
  {
        ;
  }
}
0
Как отключить оптимизацию чтобы переменная и не выбрасывалась?
0
coracio!

У меня всё нормально собирается и РАБОТАЕТ при уровнях оптимизации-O2 и -Os

Остальные флаги для компилятора:
CFLAGS = -mthumb -mcpu=cortex-m3 -fno-builtin -Wall -c -I.
0
В Ваших примерах часто приходится видеть конструкцию такого вида:

int main(void)
{
................
int i;
  while (1)
  {
        i++;

  }
}


В действительности переменная i нигде не задействована, поэтому лучше было бы написать попроще:

int main(void)
{
................
  while (1)
  {
        ;
  }
}


Попробовал собрать БЕЗ Atollic'а в Линуксе Ваш пример с плавным изменением яркости светодиода. Работает! Причём без лишней переменной i.
За пример спасибо. Удачи Вам!
0
Спасибо). Вы совершенно правы переменная i не нужна, это я на автомате оставил что сгенерил атоллик.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.