Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Чт июл 23, 2015 22:23:56

STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Рабочий код. Проверено в железе. Под CooCox. Аппаратный SPI.

Код:
// STM32F030 (STM32F103) + AD9850
// Автор: vk.com/zz555 (23.07.2015)
// Интерфейс SPI Master в STM32 - http://easystm32.ru/interfaces/45-spi-interface-part-2
// DDS generator ad9850 - http://radiokot.ru/forum/viewtopic.php?p=1688775
// Виртуальный осциллограф - http://www.zapisnyh.narod.ru/virt.htm

// PA0  - LED
// PC13 - LED (stm32f103)

// PA4 - NSS
// PA5 - SPI1_SCK
// PA6 - SPI1_MISO (Master In)
// PA7 - SPI1_MOSI (Master Out)

#include "stm32f0xx.h"      // stm32f030

#define CS_ON()            GPIOA->BRR |= GPIO_ODR_4               // stm32f030 CS - 0 (for Master)
#define CS_OFF()         GPIOA->BSRR |= GPIO_ODR_4               // stm32f030 CS - 1 (for Master)

#define LED_1            GPIOA->BSRR |= GPIO_ODR_0               // stm32f030 Управление LED
#define LED_0            GPIOA->BRR |= GPIO_ODR_0               // stm32f030

#define PC13_0            GPIOC->BSRR |= GPIO_ODR_ODR13            // PC13 OUT LED OFF      (stm32f103) Управление LED1
#define PC13_1            GPIOC->BRR |= GPIO_ODR_ODR13            // PC13 OUT LED ON      (stm32f103)
#define PC13_N            GPIOC->ODR ^= GPIO_ODR_ODR13             // PC13 OUT LED INVERT   (stm32f103)

#define SPI1_DR_8bit      (*(__IO uint8_t *)((uint32_t)&(SPI1->DR)))   // stm32f030
//#define SPI_I2S_FLAG_BSY   ((uint16_t)0x0080)                     // stm32f103

uint8_t    i;
uint8_t    data;
uint8_t    SPIData;
uint8_t    led_st;
uint32_t    TimingDelay;
uint32_t    freq;               // dds частота Hz

union un_dataword {               // 5 Байт, объединение  содержит данные для передачи AD9850
uint32_t    dataword_freq;           // 32 бит слово,  для управления частотой
uint8_t    dataword_byte[5];      // массив для побайтного доступа
}un;

// Обработчик прерываний от SPI1 (for spi slave)
void SPI1_IRQHandler(void) {
   SPIData=0;
   if ((SPI1->SR & SPI_SR_RXNE) == 1) {                        // Прерывание вызвано приемом байта?
      SPIData = SPI1->DR;                                  // Читаем то что пришло, clear flag
      if (led_st == 1) {LED_0; led_st=0;} else {LED_1; led_st=1;}    // Инвертируем состояние светодиода
      SPI1->DR = SPIData;                                  // Отправляем обратно то что приняли
   }
}

// Обработчик прерывани¤ системного таймера, прерывани¤ каждую 1 ms
void SysTick_Handler() {
   if (TimingDelay != 0) TimingDelay--;
}

// Функция временной задержки в милисекундах
void Delay_ms(uint32_t nTime) {
   TimingDelay = nTime;
   while (TimingDelay != 0) {}
}

void Delay_us() {
   uint8_t i;
   for (i=0; i<1; i++) {i++; i--;}
}

void SPISendByte(uint8_t data) {
//   CS_ON();                                     // Подаем сигнал CS слейву
//   while (!(SPI1->SR & SPI_SR_TXE));                     // убедиться, что предыдущая передача завершена (STM32F103)
   SPI1_DR_8bit=data;                              // (STM32F103) вывод на индикатор
//   SPI1->DR=data;                                 // (STM32F103) вывод на индикатор
//   while (!(SPI1->SR & SPI_SR_RXNE));                    // ждем окончания обмена (STM32F103)
   while (SPI1->SR & SPI_SR_BSY);                     // ждем конец передачи (STM32F030)
   if ((SPI1->SR & SPI_SR_RXNE) == 1) SPIData=SPI1->DR;    // если данные пришли, читаем принятые данные (STM32F030)
//   CS_OFF();                                     // Снимаем сигнал CS
}

void SetFrequency(uint32_t frequency) {
   uint8_t i;

   un.dataword_freq = (frequency*4294967296)/125000000;
   un.dataword_byte[4] = 0;

   CS_OFF();                  // FQ_UD 1
   Delay_us();
   CS_ON();                  // FQ_UD 0
   Delay_us();

   for (i=0; i<5; i++) SPISendByte(un.dataword_byte[i]);

   CS_OFF();                  // FQ_UD 1
   Delay_us();
   CS_ON();                  // FQ_UD 0
   Delay_us();
}

// Инициализация  SPI1 for STM32F030
void stm_init() {
   SystemInit();
   SysTick_Config(48000);         // Запуск прерываний на системном счетчике при частоте 48 MHz - 1ms

   RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
   RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;

   // PA4 - SPI_NSS
   // PA5 - SPI1_SCK
   // PA6 - SPI1_MISO (Master In)
   // PA7 - SPI1_MOSI (Master Out)

   GPIOA->MODER      |= (GPIO_MODER_MODER0_0 | GPIO_MODER_MODER4_0 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);
   // MODER 32 разрядный
   // 00 - по умолчанию вход
   // 01 (GPIO_MODER_MODER0_0) - выход
   // 10 (GPIO_MODER_MODER0_1) - альтернативная функция
   // 11 (GPIO_MODER_MODER0) - аналоговый режим

   GPIOA->PUPDR    |= (GPIO_PUPDR_PUPDR0_0 | GPIO_PUPDR_PUPDR4_0 | GPIO_PUPDR_PUPDR5_0 | GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR7_0);   // подтяжка к "+"
   // OPUPDR 32 разрядный
   // 00 - без подтяжки(по умолчанию)
   // 01 (GPIO_PUPDR_PUPDR0_0) - подтяжка к "+"
   // 10 (GPIO_PUPDR_PUPDR0_1) - подтяжка к "-"

   GPIOA->OSPEEDR    |= (GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7);   // 50МГц
   // OSPIDER 32 разрядный
   // x0 (GPIO_OSPEEDER_OSPEEDR0_1) - 2МГц
   // 01 (GPIO_OSPEEDER_OSPEEDR0_0) - 10МГц
   // 11 (GPIO_OSPEEDER_OSPEEDR0) - 50МГц

   GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)); // AF0 for SPI1 signals

   // Настройка SPI1
//   SPI1->CR2 = 0x0000;            // (STM32F103)
   SPI1->CR2 = (SPI_CR2_FRXTH | SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2);      // (STM32F030) 8 бит данных (0x1700)
//   SPI1->CR2 |= SPI_CR2_SSOE;       // (for slave) NSS - используется как выход управления slave select (0x0004)
//   SPI1->CR2 |= SPI_CR2_RXNEIE;   // (for slave) Включаем прерывание по приему байта (0x0040)

//   SPI1->CR1 = 0x0000;            // Slave (0x0000)
   SPI1->CR1 = SPI_CR1_MSTR;      // 1 - Мастер, 0 - Slave (0x0004)
   SPI1->CR1 |= SPI_CR1_BR;      // Маленькуя скорость SPI Baud rate = Fpclk/256   (0x0038) (2,4,8,16,32,64,128,256)
//   SPI1->CR1 |= SPI_CR1_BR_2;      // скорость SPI Baud rate = Fpclk/32 (0x0020)
   SPI1->CR1 |= SPI_CR1_SSM;      // Программный режим NSS (0x0200) (0 - for slave)
   SPI1->CR1 |= SPI_CR1_SSI;      // NSS высокий уровень, иначе мастер стане слейвом (0x0100)
   SPI1->CR1 |= SPI_CR1_SPE;      // Разрешить работу модуля SPI (0x0040)
//   SPI1->CR1 &= ~SPI_CR1_CPOL;    // Полярность тактового сигнала (CK to 0 when idle) (0x0002)
//   SPI1->CR1 &= ~SPI_CR1_CPHA;    // Фаза тактового сигнала (|= SPI_CR1_CPHA - по второму фронту) (0x0001)
//   SPI1->CR1 |= SPI_CR1_DFF;       // (STM32F103) 16 бит данных (0x0800)
   SPI1->CR1 |= SPI_CR1_LSBFIRST;   // 1 - сначала передается младший бит, 0 - сначала передается старший бит (0x0080) for dds

//   NVIC_EnableIRQ(SPI1_IRQn);       // Enable SPI1_IRQn
}

int main(void) {
   stm_init();

   LED_1;                              // stm32f030
   Delay_ms(100);
   LED_0;
   Delay_ms(300);
   LED_1;
   Delay_ms(100);
   LED_0;

//   while(1) {}                         // все работает на прерываниях (for spi slave)

   data=0;
   freq=0;                              // dds

   while(1) {                           // for dds
      freq=freq+100;
      SetFrequency(freq);
      LED_1;                           // stm32f030
      Delay_ms(10);
      LED_0;
      Delay_ms(90);
      if (freq==20000) {
         freq=0;
         SetFrequency(freq);
         Delay_ms(2000);
      }
   }

   /*
   while (1) {                           // for spi slace
      CS_ON();                         // Подаем сигнал CS слейву
      SPISendByte(data);                   // Передаем байт через SPI1
      CS_OFF();                         // Снимаем сигнал CS
       if ((data-1) == SPIData) LED_1;         // Пришли правильные данные?
                                                           // Возможно тут есть неочевидный момент. Отправляем data, а ожидаем (data-1).
                                                             // Это связано  с тем, что слейв не может передавать данные пока мастер не
                                                             // инициирует обмен данными. Таким образом если мастер сейчас передает
                                                             // число 123, то оно ему вернется когда он будет передавать следующий байт (124).
       data++;
       Delay_ms(10);
       LED_0;
       Delay_ms(200);
   }
   */
}

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Пт июл 24, 2015 09:54:10

ичо?

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июл 26, 2015 23:05:42

ТС решил похвалиться. Собсна наверно все. :)))

Если по теме, то спасибо, слизал в копилку, и отдельная благодарность за нормальную инициализацию путем обращения к регистрам, а не всякие там CMSIS-овские initStructure

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Пн июл 27, 2015 08:15:46

Cat писал(а): а не всякие там CMSIS-овские initStructure
Это и есть CMSIS, структуры в SPL.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Пт июл 31, 2015 15:49:21

ave101 писал(а):
Рабочий код.


Реально? :)))

Код:
// Обработчик прерываний от SPI1 (for spi slave)
void SPI1_IRQHandler(void) {





Код:
//   NVIC_EnableIRQ(SPI1_IRQn);       // Enable SPI1_IRQn

Код:
//   while(1) {}                         // все работает на прерываниях (for spi slave)



И собственно - на кой здесь прерывания да еще и слейва ?

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вт авг 04, 2015 17:53:39

dosikus писал(а):
ave101 писал(а):Рабочий код.

Реально? :)))

И собственно - на кой здесь прерывания да еще и слейва ?

Реально.

Все, что закомментировано, относится к созданию связи по SPI между двумя контроллерами.
Прием осуществляется в прерывании.
Этот код шпаргалка для разных случаев.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Сб июн 04, 2016 10:27:32

Config CooCox: View->Repository
http://cs615821.vk.me/v615821100/15928/0wQ3j6JByGY.jpg

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 05:50:56

Дабы не плодить новую тему, спрошу у уважаемых знатоков здесь...
Ситуация такова. По какой-то невыясненной причине недавно приобретённый ST-Link V.2 не "видит" камень STM32F030P4. При том, что он отлично "видит" STM32F100C4, STM32F100RB, STM32F103C8. Это из ST_Link утилиты и из Кейла и из Кокоса. Но в то же время Jet Link 8 прекрасно "видит" все перечисленные выше камни из J_Flash и Кейла. Как такое может быть? Вывод BOOT F030 подключал и на землю и на питание - ничего не меняется. Осциллографом наличие, что SWCLK, что SWDIO подтверждается. Можно было бы погрешить на партию F030, но ведь J_Link-ом программируется и работает нормально. ST-Link проапгрейдил до последней версии. Подскажите, пожалуйста, в какую сторону копать? Спасибо.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 08:08:18

Тему Вы конечно "удачную" выбрали для своего вопроса.
Попробуйте стереть камень прогой STM32 ST-LINK Utility. Я как-то что такое залил в 103 и кокос перестал его видеть :dont_know: , когда стер этой утилиткой то все опять заработало.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 08:13:53

s_black писал(а): ST-Link V.2 не "видит" камень STM32F030P4.


VDDA подключен?

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 13:19:33

dosikus писал(а):
s_black писал(а): ST-Link V.2 не "видит" камень STM32F030P4.


VDDA подключен?

Конечно подключен! Вот я прямо на месте вытыкаю шлейф из ST-Link-а и втыкаю его в J-Link ничего не меняя на макетке. В итоге J-Link прекрасно всё читает, пишет и пр. Даже не знаю, что и думать (((

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 13:20:30

Z_h_e писал(а):Тему Вы конечно "удачную" выбрали для своего вопроса.
Попробуйте стереть камень прогой STM32 ST-LINK Utility.

Так вот именно эта утилита и не видит камня (((

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 14:45:12

s_black , STLink конечно же огрызок с али.
Я дообновлялся , пришлось сдувать чип и ставить 103ий
http://kazus.ru/forums/showthread.php?t ... A%EB%EE%ED

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 16:19:56

dosikus писал(а):s_black , STLink конечно же огрызок с али.
Я дообновлялся , пришлось сдувать чип и ставить 103ий
http://kazus.ru/forums/showthread.php?t ... A%EB%EE%ED

С Али, конечно же! ))) Но не огрызок - нормальный "брелок". Остальные камни читает без проблем.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 16:59:34

Огрызок потому что у него нет транслятора уровней.
Пробовать обновить STlink utility , затем обновить прошивку STLink.
Но возможен печальный исход- придется перекатывать чип и шить ...

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 17:34:29

Не знаю, вроде бы это http://ru.aliexpress.com/item/1pcs-New- ... 94909.html не огрызок, хотя...

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 19:46:17

s_black, нет этот полноценный. Здесь есть транслятор уровней.
И вот здесь нужно обязательно подавать на Vtarget ( Если не ошибаюсь PIN1 разъма) напряжение питание с отлаживаемой платы.
Так же как и на JLink8.
Сие сделано?
Ну и как выше писал - поставить STlink utility свежую и проапгрейдить прошивку STLink.

Изображение

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 20:18:18

Да, всё так и делаю: и питание, и свежая утилита, и апгрейд. Говорю же - остальные камни отлично определяются, читаются и пишутся, только 030, как заколдованный. Попробую завтра с другим камнем из этой же партии.

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 20:22:40

s_black . а что куда подсоединяем?
Было неоднократно что соединяли длинным шлейфом, коннекта не было.
У меня что JLink и V8 и 072 что STLINK подсоединяю одиночными проводами 15см - полет норамльный.
И что пишет в лог STLink?

Re: STM32F030 (STM32F103) и генератор до 40 МГц AD9850

Вс июн 05, 2016 20:28:30

Я ж Вам говорю - работаю с 030 через J-Link Кейле - всё шьёт и читает. Отсоединяю шлейф ТОЛЬКО от программатора, ничего не меняя на макетке и перестыковую его на СТ-линк, а на выходе болт. Утилита пишет, что не может законнектить таржет и просит выбрать коннект анде ресет. После такового выбора всё равно ни фига.
Ответить