Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 17.12.2013, 19:24  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию STM32 - Tips 'N Tricks

Предлагаю выкладывать здесь полезные мелочи (и не только) при работе с STM32, которые могут запросто потеряться в других ветках или на просторах инета.
Реклама:
nahimovv вне форума  
Эти 9 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-shiva- (28.12.2013), akegor (19.04.2014), dadigor (18.12.2013), dosikus (17.12.2013), gary2007 (27.12.2013), neyvert (18.12.2013), tempora (18.12.2013), ut1wpr (18.12.2013), Zoosman (24.04.2015)
Непрочитано 17.12.2013, 19:35  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию Бага TIM1

Бага TIM1 во многих линейках STM32.
При cоединении в цепочку двух таймеров, когда TIM1 настроен как slave и Gated Mode, происходит самопроизвольный запуск TIM1 при попытке Update generation регистра TIM1-›EGR.
nahimovv вне форума  
Эти 3 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-shiva- (28.12.2013), dosikus (17.12.2013), MikhailSh (19.01.2016)
Непрочитано 17.12.2013, 20:18  
dosikus
Гуру портала
 
Аватар для dosikus
 
Регистрация: 20.11.2004
Сообщений: 10,018
Сказал спасибо: 936
Сказали Спасибо 2,270 раз(а) в 1,565 сообщении(ях)
dosikus на пути к лучшему
По умолчанию Re: STM32 - Tips 'N Tricks

Расчет BRR USART в противовес простыням SPL.
Код:
#define USARTCLK 48000000UL
#define BAUDRATE 115200UL
где USARTCLK частота тактирования USART в Гц.
Тактирование может быть и от APB и от HSI

Код:
USARTx-›BRR =(USARTCLK+BAUDRATE/2)/BAUDRATE;
__________________
Осторожно , злой кот
dosikus вне форума  
Сказали "Спасибо" dosikus
-shiva- (28.12.2013)
Непрочитано 17.12.2013, 20:35  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию Злокопипаст

Злокопипаст документации.
В инете наблюдались жалобы на "невозможность" каскадировать некоторые таймера в один 32-ух разрядный, хотя в таблицах UM данное каскадирование описано как допустимое. Это типа TIM16--›TIM15 в STM32F100, TIM10--›TIM9 в STM32F20X и т.д.. Так как все таймера STM32, по сути, одинаковы, то налицо злокопипаст документации. На самом деле там всё просто, в качестве TRGO выступает OCx. Т.е. нужно настроить ведущий таймер в режиме PWM1, разрешить выход, альтернативную функцию пина можно не включать, если это не нужно.
nahimovv вне форума  
Эти 5 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-shiva- (28.12.2013), dadigor (18.12.2013), dosikus (18.12.2013), neyvert (18.12.2013), ut1wpr (18.12.2013)
Непрочитано 17.12.2013, 20:38  
dosikus
Гуру портала
 
Аватар для dosikus
 
Регистрация: 20.11.2004
Сообщений: 10,018
Сказал спасибо: 936
Сказали Спасибо 2,270 раз(а) в 1,565 сообщении(ях)
dosikus на пути к лучшему
По умолчанию Re: STM32 - Tips 'N Tricks

swo.h
Код:
 
#ifndef _SWO_H       
#define _SWO_H  

void SWO_PrintChar (char c);
void SWO_PrintString(const char *s);

#endif
swo.c
Код:
/**************************************************  *********************************
* 
*
* Defines for Cortex-M debug unit
*/
#define ITM_STIM_U32 (*(volatile unsigned int*)0xE0000000) // STIM word acces
#define ITM_STIM_U8 (*(volatile char*)0xE0000000) // STIM byte acces 
#define ITM_ENA (*(volatile unsigned int*)0xE0000E00) // ITM Enable
#define ITM_TCR (*(volatile unsigned int*)0xE0000E80) // ITM Trace Control Reg.
#define DHCSR (*(volatile unsigned int*)0xE000EDF0) // Debug register
#define DEMCR (*(volatile unsigned int*)0xE000EDFC) // Debug register
/**************************************************  **********************************
*
* Function description
* Prints a character to the ITM_STIM register in order to provide data for SWO
*/
void SWO_PrintChar(char c) {
//
// Check if SWO is set up. If it is not, return to avoid that a program
// hangs if no debugger is connected.
//
//
// Check if DEBUGEN in DHCSR is set
//
if ((DHCSR & 1)!= 1) {
return;
}
//
// Check if TRACENA in DEMCR is set
//
if ((DEMCR & (1 ‹‹ 24)) == 0) {
return;
}
//
// Check if ITM_TRC is enabled
//
if ((ITM_TCR & (1 ‹‹ 22)) == 1) {
return;
}
//
// Check if stimulus port 0 is enabled
//
if ((ITM_ENA & 1) == 0) {
return;
}
//
// Wait until STIMx is ready to accept at least 1 word
//
while ((ITM_STIM_U8 & 1) == 0);

ITM_STIM_U8 = c;
}
/**************************************************  **********************************
*
* SWO_PrintString
*
* Function description
* Prints a string via SWO
*
*/
void SWO_PrintString(const char *s) {
//
// Print out character per character
//
while (*s) {
SWO_PrintChar(*s++);
}
}
Вывод строк через swo .
Выдрано из мануала JLink .Проверено в IAR, Keil, Eclipse
Подключаем файлы к проекту . Подключаем PB3 (конфигурация по умолчанию) к SWO Jlink .
В IAR отметить General options , вкладка Library Configuration -› Library low-level interface implementation -› Via SWO
В Keil в настройках дебуггера разрешить trace.
Выхлоп наблюдаем в терминалах дебуггеров.
__________________
Осторожно , злой кот

Последний раз редактировалось dosikus; 17.12.2013 в 20:40.
dosikus вне форума  
Эти 6 пользователя(ей) сказали Спасибо dosikus за это сообщение:
-shiva- (28.12.2013), dadigor (18.12.2013), Easyrider83 (18.12.2013), kot-69 (20.12.2013), LiVit (16.03.2017), tempora (18.12.2013)
Непрочитано 18.12.2013, 00:15  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию Обращение к порту

Многие знают, а многие и не догадываются, что к многим ресурсам STM32 можно обратиться как к слову (32бит), полуслову (16бит) и как к байту (8бит).
Например, такое:
Код:
#define GPIOB_Low             (*(__IO uint8_t *)((uint32_t)&(GPIOB-›ODR))) 
#define GPIOB_High            (*(__IO uint8_t *)((uint32_t)&(GPIOB-›ODR) + 1))
позволяет получить доступ к младшему байту порта, не затрагивая старший, и наоборот. Доступно как для чтения, так и для записи. На стандартных методах обращения к порту это никак не отражается, они абсолютно ликвидны.

Запись
Код:
#define LCD_DATA             (*(__IO uint8_t *)((uint32_t)&(GPIOB-›ODR)))
позволяет оперировать шиной LCD 8бит, подключённой к PB0-PB7, без дополнительных телодвижений.
Код:
LCD_DATA = 0xA5;
nahimovv вне форума  
Эти 13 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-jonns- (20.12.2013), -shiva- (28.12.2013), dadigor (18.12.2013), danilych2 (10.08.2016), dosikus (18.12.2013), Easyrider83 (18.12.2013), kot-69 (01.01.2014), MaxiMuz79 (20.12.2013), neyvert (18.12.2013), Romsb (30.01.2016), Sl_ (23.01.2016), Unknown (26.03.2015), Uvavan (13.06.2014)
Непрочитано 18.12.2013, 13:08  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию SPI 8bit STM32F0XX

При освоении STM32F0XX новички часто испытывают трудности запуска SPI в режиме 8бит и ниже. Причиной этому является значительное расширение возможностей модуля SPI, по сравнению с предшественниками, и некоторые изменения в работе модуля.

Что делать:

1. По умолчанию доступ к SPIx-›DR 16бит. Чтобы получить доступ к SPIx-›DR как к регистру 8бит пишем:

Код:
#define SPI1_DR_8bit          (*(__IO uint8_t *)((uint32_t)&(SPI1-›DR))) 
#define SPI2_DR_8bit          (*(__IO uint8_t *)((uint32_t)&(SPI2-›DR)))
Теперь обращаемся к регистру данных так:

Код:
SPI1_DR_8bit = 0x34;
SPI2_DR_8bit = 0x78;
2. По умолчанию и при запрещённых установках DS [3:0]: Data size регистра SPIx_CR2 устанавливается длина данных 16бит (1111: 16-bit). Поэтому при настройке длины данных логичнее сбрасывать, а не устанавливать определённые биты. Иначе при любой попытке записи некорректного значения, регистр SPIx_CR2 автоматически восстановит длину данных 16бит.
Т.е. для того чтобы установить длину 8бит нужно просто сбросить старший бит DS [3:0] регистра SPIx_CR2.

3. Также встречались жалобы на непонятное поведение бита RXNE. Всё дело в бите FRXTH регистра SPIx_CR2, при работе с данными 8бит требуется его установить .
nahimovv вне форума  
Эти 11 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-shiva- (28.12.2013), arhiv_6 (12.06.2017), dadigor (18.12.2013), dimka11 (09.09.2015), dosikus (19.12.2013), Easyrider83 (17.03.2017), kot-69 (01.01.2014), MikhailSh (24.10.2017), neyvert (18.12.2013), ut1wpr (18.12.2013)
Непрочитано 19.12.2013, 21:23  
nahimovv
Заблокирован
 
Регистрация: 25.04.2013
Сообщений: 1,431
Сказал спасибо: 0
Сказали Спасибо 385 раз(а) в 254 сообщении(ях)
nahimovv на пути к лучшему
По умолчанию TIM + DMA

Изюминкой STM32, ИМХО, является возможность связывать таймера между собой и широкие возможности DMA. Здесь возможности практически безграничны, что позволяет делать многие вещи по сути хардварными.
Процесс этот, порой, мозговыносящий и без хороших знаний работы модулей МК, логического анализатора и других средств отладки не сулит ничего хорошего. Однако результаты того стоят.

Самый простой пример - подключение 4-х разрядного LED-семисегментника с общим анодом (максимум до 8 разрядов). Сегменты подключены к PA0-PA7 через резисторы 200 Ом, аноды - к PA8-PA11 непосредственно, без ключей.
Всё это подключалось к STM32F0Discovery, МК STM32F051. Особенностью такого подключения является разнояркость разрядов, для компенсации которой был тоже задействован DMA. Итого задействовано - 1 таймер и 2 канала DMA (при подключении ключей в цепях анодов достаточно 1 таймера и 1 канала DMA). Результат - нет прерываний, обновление информации и коррекция разнояркости по сути хардварное.

Как это работает:

В общем случае - таймер периодически пинает DMA, DMA загружает данные из буфера в порт, в данном случае это GPIOA. Т.к. сегменты и разряды подключены к одному порту и их коммутация происходит одновременно, то никакого гашения/включения разрядов на время смены информации на сегментах не требуется, подсветка нерабочих сегментов отсутствует.

В данном случае, с коррекцией разнояркости - сначала таймер пинает один канал DMA для загрузки TIM_ARR, чем и определяется яркость разряда, потом пинает другой канал DMA, который и загружает порт данными о текущем разряде и состоянии сегментов.


Примерный код:

Здесь всё стандартно и ничего интересного.
Код:
#define LOW_BYTE(var)    (*(__IO uint8_t *)((uint32_t)&(var)))
   
#define DIGITS          0x04    // количество разрядов LED
#define LED_PORT        GPIOA

#define DIGIT_1     GPIO_ODR_11
#define DIGIT_2     GPIO_ODR_8
#define DIGIT_3     GPIO_ODR_9
#define DIGIT_4     GPIO_ODR_10

#define DIGIT_5     GPIO_ODR_12
#define DIGIT_6     GPIO_ODR_13
#define DIGIT_7     GPIO_ODR_14
#define DIGIT_8     GPIO_ODR_15

#define SEG_A       GPIO_ODR_0
#define SEG_B       GPIO_ODR_2
#define SEG_C       GPIO_ODR_6
#define SEG_D       GPIO_ODR_4
#define SEG_E       GPIO_ODR_3
#define SEG_F       GPIO_ODR_1
#define SEG_G       GPIO_ODR_7
#define SEG_H       GPIO_ODR_5

const uint8_t ten2led[] =
{
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,          // "0"
SEG_B | SEG_C,                                          // "1"
SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,                  // "2"
SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,                  // "3"
SEG_F | SEG_G | SEG_B | SEG_C,                          // "4"
SEG_A | SEG_F | SEG_G | SEG_D | SEG_C,                  // "5"
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,          // "6"
SEG_A | SEG_B | SEG_C,                                  // "7"
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,  // "8"
SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,          // "9"

SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,          // "A"
SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,                  // "b"
SEG_A | SEG_D | SEG_E | SEG_F,                          // "C"
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,                  // "d"
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,                  // "E"
SEG_A | SEG_E | SEG_F | SEG_G,                          // "F"
0x00                                                    // " "

};

uint32_t tmp  = 0; 
uint32_t ttmp = 0;

uint8_t Ress[11];
Здесь содержится информация о разрядах и сегментах, которые DMA загружает в порт. Старшие байты DIGIT_Х содержат информацию о включённом разряде (в данном случае "1" соответствует включённому разряду) и при выполнении программы меняться не должны!
Младшие байты содержат информацию о включённых сегментах. Изначально содержат 0xFF, т.е. все сегменты выключены.
Код:
uint16_t Data_Buffer[DIGITS]= 
{
DIGIT_1 | 0xFF, DIGIT_2 | 0xFF, DIGIT_3 | 0xFF, DIGIT_4 | 0xFF
    
};
Здесь содержатся значения яркости для каждого разряда которые DMA заносит в таймер. Изначально содержатся базовые значения яркости.
Код:
uint16_t TIM_Buffer[DIGITS]= 
{
1000, 1000, 1000, 1000
    
};
Здесь содержатся значения яркости для различных высвечиваемых символов. 1000 - наибольшая яркость, 770 - наименьшая.
В данном случае значений всего три, что вполне достаточно. В других случаях можно задать для каждого символа свои значения.
Код:
const uint16_t TIM_ARR_val[] =
{
1000,   // "0"
770,    // "1"
920,    // "2"
920,    // "3"
920,    // "4"
920,    // "5"
1000,   // "6"
770,    // "7"
1000,   // "8"
1000,   // "9"

1000,   // "A"
920,    // "b"
920,    // "C"
920,    // "d"
920,    // "E"
920,    // "F"
770,    // " "

};
Настройки DMA, как по учебнику, ничего особенного.
Код:
void Init_DMA(void)
{    
RCC-›AHBENR |= RCC_AHBENR_DMA1EN;
    
DMA1_Channel3-›CPAR = (uint32_t)&GPIOA-›ODR;     // DMA channel x peripheral address register
DMA1_Channel3-›CMAR = (uint32_t)Data_Buffer;     // DMA channel x memory address register    
DMA1_Channel3-›CNDTR = DIGITS;                   // DMA channel x number of data register

DMA1_Channel3-›CCR  |=  DMA_CCR_MSIZE_0;         // Memory size 16 bit
DMA1_Channel3-›CCR  |=  DMA_CCR_PSIZE_0;         // Peripheral size 16 bit

DMA1_Channel3-›CCR  |=  DMA_CCR_PL_1;            // Channel Priority level High 
DMA1_Channel3-›CCR  |=  DMA_CCR_MINC;            // Memory increment mode 
DMA1_Channel3-›CCR  |=  DMA_CCR_CIRC;            // Circular mode
DMA1_Channel3-›CCR  |=  DMA_CCR_DIR;             // Data transfer direction Memory -› Peripheral

DMA1_Channel3-›CCR  |=  DMA_CCR_EN;              // Channel enable

//---------------------------
DMA1_Channel4-›CPAR = (uint32_t)&TIM3-›ARR;      // DMA channel x peripheral address register
DMA1_Channel4-›CMAR = (uint32_t)TIM_Buffer;      // DMA channel x memory address register    
DMA1_Channel4-›CNDTR = DIGITS;                   // DMA channel x number of data register

DMA1_Channel4-›CCR  |=  DMA_CCR_MSIZE_0;         // Memory size 16 bit
DMA1_Channel4-›CCR  |=  DMA_CCR_PSIZE_0;         // Peripheral size 16 bit

DMA1_Channel4-›CCR  |=  DMA_CCR_PL;              // Channel Priority level Very High 
DMA1_Channel4-›CCR  |=  DMA_CCR_MINC;            // Memory increment mode 
DMA1_Channel4-›CCR  |=  DMA_CCR_CIRC;            // Circular mode
DMA1_Channel4-›CCR  |=  DMA_CCR_DIR;             // Data transfer direction Memory -› Peripheral

DMA1_Channel4-›CCR  |=  DMA_CCR_EN;              // Channel enable

}
Настройка таймера.
Настройка предделителя: (SystemCoreClock/(DIGITS * 50 * 1000)) - 1, где 50 значение в герцах на один разряд, 1000 - базовая константа яркости.
TIM3-›ARR = 1000 - 1, где 1000 - базовая константа яркости на время настройки таймера. При работе изменяется через DMA.
TIM3-›CCR1 = 25, где 25 - абстрактная константа, определяет промежуток времени между загрузкой значения яркости для разряда и последующим обновлением GPIOA.
Код:
void Init_TIM3(void)
{
RCC-›APB1ENR |= RCC_APB1ENR_TIM3EN;   // TIM3 clock enable

TIM3-›PSC  = (SystemCoreClock/(DIGITS * 50 * 1000)) - 1;  //240 
TIM3-›ARR  = 1000 - 1;

TIM3-›CCR1 = 25;                                    
        
TIM3-›DIER  |= TIM_DIER_UDE;                    // Upload DMA Enable
TIM3-›DIER  |= TIM_DIER_CC1DE;
        
TIM3-›CR1   |= TIM_CR1_CEN | TIM_CR1_ARPE;      // Counter Enable

}
Bin2BCD, в коментах не нуждается.
Код:
uint32_t Bin2BCD(uint32_t value, uint8_t *Res)
{
uint8_t *n = Res;

while (value › 0)
 {
 *Res++ = value % 10;
 value /= 10;
 }

return (uint32_t)(Res - n);
 
}
Примерный майн - инкрементальный счётчик с инкрементом значения через ~100 миллисекунд.
Код:
int main(void)
{
 
Init_GPIO();	

Init_DMA();    
Init_TIM3();    

while(1)
 {
   Bin2BCD(tmp, Ress);
   ttmp = DIGITS;
     
   while(ttmp--)
    {        
     TIM_Buffer[ttmp] = TIM_ARR_val[Ress[ttmp]];           // Загружается значение яркости в соответствии с высвечиваемым  
                                                           // символом для соответствующего разряда
     LOW_BYTE(Data_Buffer[ttmp]) = ~ten2led[Ress[ttmp]];   // Загружаются данные по сегментам для соответствующего разряда
        
    }

   TIM_Buffer[1] += 100;                                   // Для децимальной точки увеличиваем яркость    
   LOW_BYTE(Data_Buffer[1]) -= SEG_H;                      // Засвечиваем точку в соответствующем разряде
    
   tmp++;
                          
   Delay_mS(100);  // delay 100ms
    
 }    

while(1); 
 
}

Последний раз редактировалось nahimovv; 20.12.2013 в 23:44.
nahimovv вне форума  
Эти 11 пользователя(ей) сказали Спасибо nahimovv за это сообщение:
-jonns- (21.03.2017), -shiva- (28.12.2013), dadigor (05.09.2016), dosikus (19.12.2013), kot-69 (20.12.2013), krug_vv (21.12.2013), MaxiMuz79 (20.12.2013), neyvert (28.12.2013), Nick19 (26.04.2015), sun4in (21.12.2013), ut1wpr (20.12.2013)
Непрочитано 08.08.2016, 14:35  
sokolav
Частый гость
 
Регистрация: 31.03.2006
Сообщений: 40
Сказал спасибо: 2
Сказали Спасибо 7 раз(а) в 7 сообщении(ях)
sokolav на пути к лучшему
По умолчанию Быстый вывод отладочной инфармации Real Time Transfer

Обнаружил для себя новый быстрый вывод отладочный информации - Real Time Transfer.
Работает только с отладчиком J-Link. Подробно на сайте https://www.segger.com/jlink-rtt.html
Там же можно бесплатно скачать. Пример работы с RTT в моем архиве.
Вложения:
Тип файла: rar Segger.rar (1.26 Мб, 0 просмотров)
sokolav вне форума  
 

Закладки

Метки
stm32
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Изучаем STM32 Cortex M3 EugVor ARM 6166 19.02.2024 18:22
STM32 и 9 бит SPI... всё так плохо? st__1 Микроконтроллеры, АЦП, память и т.д 94 07.08.2012 21:05
Проблема с ST-LINK +KEIL + STM32 LionRJ Микроконтроллеры, АЦП, память и т.д 5 06.03.2012 17:21
stm32 DISCOVERY-контроллер ШД ATMExpert Микроконтроллеры, АЦП, память и т.д 27 14.09.2011 17:08


Часовой пояс GMT +4, время: 02:50.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot