Чт июл 23, 2015 22:23:56
// 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);
}
*/
}
Пт июл 24, 2015 09:54:10
Вс июл 26, 2015 23:05:42
Пн июл 27, 2015 08:15:46
Это и есть CMSIS, структуры в SPL.Cat писал(а): а не всякие там CMSIS-овские initStructure
Пт июл 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)
Вт авг 04, 2015 17:53:39
dosikus писал(а):ave101 писал(а):Рабочий код.
Реально?
И собственно - на кой здесь прерывания да еще и слейва ?
Сб июн 04, 2016 10:27:32
Вс июн 05, 2016 05:50:56
Вс июн 05, 2016 08:08:18
Вс июн 05, 2016 08:13:53
s_black писал(а): ST-Link V.2 не "видит" камень STM32F030P4.
Вс июн 05, 2016 13:19:33
dosikus писал(а):s_black писал(а): ST-Link V.2 не "видит" камень STM32F030P4.
VDDA подключен?
Вс июн 05, 2016 13:20:30
Z_h_e писал(а):Тему Вы конечно "удачную" выбрали для своего вопроса.
Попробуйте стереть камень прогой STM32 ST-LINK Utility.
Вс июн 05, 2016 14:45:12
Вс июн 05, 2016 16:19:56
dosikus писал(а):s_black , STLink конечно же огрызок с али.
Я дообновлялся , пришлось сдувать чип и ставить 103ий
http://kazus.ru/forums/showthread.php?t ... A%EB%EE%ED
Вс июн 05, 2016 16:59:34
Вс июн 05, 2016 17:34:29
Вс июн 05, 2016 19:46:17
Вс июн 05, 2016 20:18:18
Вс июн 05, 2016 20:22:40
Вс июн 05, 2016 20:28:30