Главная » Статьи » Уроки по программированию stm32fxxx » Уроки по программированию stm32f1xx

Урок 3: Помигаем светодиодом с StdPeriph
В прошлом уроке мы помигали светодиодом вручную заполняя все регистры. библиотека StdPeriph позволяет это сделать неявно, не обращаясь к портам напрямую.

Создаём новый проект, как описано в уроке 1.

Скачиваем саму библиотеку: StdPeriph. Или с этого сайта из раздела Каталог файлов

Из неё копируем папку StdPeriph в папку с проектом. Рядом рассмотренный ранее CMSIS. Если вы скачаете StdPeriph с сайта www.st.com то там так же обнаружите CMSIS, подходящий под версию StdPeriph. Нам нужны именно папочки CMSIS и Stdperiph. Только в моём архиве файл _conf.h лежит в папке stdperiph/inc, а в скачанном с официального сайта, в папках с примерами.

Теперь, как и раньше, создаём группы со следующими названиями:
1) startup - для файла начальной инициализации. просто переименовывается существующая группа.
2) CMSIS - для библиотеки CMSIS
3) User - для файлов пользователя
4) StdPeriph - для библиотеки StdPeriph.

В которые добавляем файлы:
2) В CMSIS добавляем core_cm3.c
3) В User main.c
4) В StdPeriph добавляем все файлы *.с из папки src в StdPeriph.

В файле main.c напишите следующий основной код:

#include "stm32f10x.h"

int main(void)
{
   
}


В итоге у вас должно получиться следующее:



Пока проект не соберётся.


Теперь щёлкните правой кнопкой мыши по Target1 -> Options for Target 'Target 1'. Во вкладке С/С++ пропишите пути к папкам, в которых программа будет искать библиотеки. У вас должно получиться следующее:



У файла stm32f10x.h снимите галочку только чтение. Нам сейчас придётся его править.

Во-первых раскомментируйте define, относящийся к вашему устройству. Эта процедура описана в прошлом уроке.

Примечание: Если вы используете библиотеку, скачанную с нашего сайта, то файл уже будет разблокирован и USE_STDPERIPH_DRIVER раскомментировано.

Во-вторых найдите строки:
#if !defined  USE_STDPERIPH_DRIVER
/**
 * @brief Comment the line below if you will not use the peripherals drivers.
   In this case, these drivers will not be included and the application code will
   be based on direct access to peripherals registers
   */
  /*#define USE_STDPERIPH_DRIVER*/

#endif

Раскомментируйте строку /*#define USE_STDPERIPH_DRIVER*/. Это значит, что вы собираетесь использовать библиотеку STDPERIPH.

Второй тонкий момент.
Найдите чуть ниже строку:
#define HSE_VALUE ((uint32_t)8000000)

Тут указана тактовая частота нашего кварца. Измените её, если вы используете кварц отличный от 8МГц.

Теперь найдите в папке со скачанной библиотекой файлы: stm32f10x_conf.h и system_stm32f10x.c по пути: STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Template. Второй файл, как вы помните, раньше входил в состав библиотеки CMSIS.
Поместите их в папку user и добавьте к проекту в группу user.

Примечание: Как уже писалось выше, если вы скачали архив в нашего сайта, то файл stm32f10x_conf.h будет лежать по адресу stdperiph/inc и переносить его не обязательно, достаточно просто добавить в проект.

Всё. Теперь всё должно откомпилиться. Библиотека добавлена.

В файле stm32f10x_conf.h находится список всех файлов из библиотеки stdperiph. Комментируя те или иные строки, можно подключать или отключать часть файлов. В нашем случае нам понадобятся только файлы stm32f10x_rcc.h и stm32f10x_gpio.h, отвечающие за тактирование и порты ввода-вывода соответственно. А также misc.h.

Для инициализации порта в StdPeriph используется специальная структура следующего вида:
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */


GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */


GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */

}GPIO_InitTypeDef;

В пользовательской программе переменная этого типа объявляется так:

GPIO_InitTypeDef PORTA_init_struct;

Теперь следуем следущему плану:
1) Включаем тактирование порта.
2) Заполняем структуру.
3) Вызываем функцию инициализации порта по этой структуре.

1) Тактирование включается следующим образом:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

Где вместо RCC_APB2Periph_GPIOA пишете порт, который хотите затактировать, например: RCC_APB2Periph_GPIOB. Или, если надо затактировать USART, то RCC_APB2Periph_USART1.

2) Заполняем структуру:

PORTA_init_struct.GPIO_Pin = GPIO_Pin_9;
PORTA_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
PORTA_init_struct.GPIO_Mode = GPIO_Mode_Out_PP;

Примечание: Если вы используете более позднюю библиотеку или библиотеку для другой серии, то там может быть немного другая структура данных.
Тогда МК должен быть инициализирован так:

GPIO_InitType.GPIO_Pin = GPIO_Pin_9;
GPIO_InitType.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitType.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitType. GPIO_OType = GPIO_OType_PP;
GPIO_InitType. GPIO_PuPd = GPIO_PuPd_NOPULL;

В графу GPIO_Pin записываем номер ножки, которую инициализируете или список ножек через | в виде GPIO_Pin_Х, где Х - номер ножки.

В графу GPIO_Speed записываем скорость порта. Чем выше скорость, тем быстрее он будет переключаться из одного состояния в другое. Но при этом будет больше энергопотребление.
Выбирать можно из трёх вариантов:
1) GPIO_Speed_10MHz
2) GPIO_Speed_2MHz
3) GPIO_Speed_50MHz

В графу GPIO_Mode записывается режим работы вывода. Это самая главная опция в структуре. Режимы работы были рассмотрены в предыдущем уроке. Вот как они описаны в StdPeriph:
1) GPIO_Mode_AIN - аналоговый вход. Нужен для работы АЦП.
2) GPIO_Mode_IN_FLOATING - вход с открытым коллектором.
3) GPIO_Mode_IPD - Вход с подтяжкой к земле.
4) GPIO_Mode_IPU - Вход с подтяжкой к питанию.
5) GPIO_Mode_Out_OD - Выход с открытым коллектором.
6) GPIO_Mode_Out_PP - Выход с подтяжкой.
7) GPIO_Mode_AF_OD - Альтернативный выход с открытым коллектором.
8) GPIO_Mode_AF_PP - Альтернативный выход с подтяжкой.

3) Теперь запишем настройки в порт:

GPIO_Init(GPIOA, &PORTA_init_struct);

Тут просто: Первым пишем название порта в виде GPIOХ, где Х - номер порта. А вторым пишем указатель на структуру.
Напишем следующий код:

#include "stm32f10x.h"

void Delay( unsigned int Val);

int main(void)
{
GPIO_InitTypeDef GPIO_InitPort;

// Enable PORTB Periph clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitPort.GPIO_Pin = GPIO_Pin_0;
GPIO_InitPort.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPort.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitPort);

GPIO_InitPort.GPIO_Pin = GPIO_Pin_1;
GPIO_InitPort.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPort.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitPort);

while(1)
{
    GPIO_SetBits( GPIOB, GPIO_Pin_0);
    GPIO_ResetBits( GPIOB, GPIO_Pin_1);
    Delay( 600000);
 
    GPIO_ResetBits( GPIOB, GPIO_Pin_0);
    GPIO_SetBits( GPIOB, GPIO_Pin_1);
    Delay( 600000);
}
}


void Delay(vu32 nCount)
{
  for(; nCount!= 0;nCount--);
}

Теперь соберём всё и зашьём. Светодиод должен мигать.

Примечание по созданию папок для файлов: В их названиях не должно быть пробелов. Иначе будет прочитано последнее слово и выдана ошибка файла core_m3.c
Категория: Уроки по программированию stm32f1xx | Добавил: Korvin (01.11.2011)
Просмотров: 11490 | Комментарии: 7 | Рейтинг: 5.0/1
Всего комментариев: 7
7 michaelbar  
0
Добрый день. Нужна помощь. Делаю лабораторную по stm32.  "поморгать светодиодами". Код сделал. загрузил. Все работает. Но для проверки необходимо вставить две функции. Чего-то не клеится. Не пойму куда в программу вставлять эти две функции. работу делаю в Keil4.
вот инструкция по проверки работы:
Использование библиотеки для проверки
Подключение
Для использования библиотеки для проверки правильности выполнения лабораторной работы необходимо выполнить следующие действия:
1) Сбросить файлы Lab2_Test.h и Lab2_Test.lib в папку, где лежит main.c.
2) В проект добавить эти 2 файла: Lab2_Test.lib и соответствующий ему Lab2_Test.h файл. Для использования функций из библиотеки в файле, в котором планируется использовать эти функции необходимо прописать строку:
#include “Lab2_Test.h”
Использование библиотеки Lab2_Test
Данная библиотека имеет только 2 функции.
Первая:
void Lab2_Test_ini(uint8_t variant_num);
Инициализирует проверяющий код. В качестве входного параметра принимает номер варианта.
Вторая:
uint32_t read_flag(void);
Данная функция считывает какие светодиоды и в какой последовательности включаются и выдаёт решение о правильности выполнения лабораторной работы.
Ответ программа выдаёт не мгновенно. Ей требуется некоторое время на анализ порядка включения светодиодов.

вот код из файла Lab2_Test.h :
Код:#ifndef BUTTON_TEST_H
#define BUTTON_TEST_H

#include "stm32f4xx.h"
#include "stdio.h"

void Lab2_Test_ini(uint8_t variant_num);
uint32_t read_flag(void);
#endif
Вот код моей программы:
Код:#include "stm32f4xx.h"
#include "Lab2_Test.h"

uint32_t i;

int main(void)
{
   GPIO_InitTypeDef GPIO_struct_LED;
   
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
   
   GPIO_struct_LED.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_struct_LED.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_struct_LED.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_struct_LED.GPIO_OType = GPIO_OType_PP;
  GPIO_struct_LED.GPIO_PuPd = GPIO_PuPd_NOPULL;
   
  GPIO_Init(GPIOD, &GPIO_struct_LED);
      
while(1) {
   GPIO_SetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}
      
      GPIO_SetBits(GPIOD, GPIO_Pin_12);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_12);
   for(i=0;i<1000000;i++) {}
      
   GPIO_SetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}

GPIO_SetBits(GPIOD, GPIO_Pin_15);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_15);
   for(i=0;i<1000000;i++) {}

GPIO_SetBits(GPIOD, GPIO_Pin_12);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_12);
   for(i=0;i<1000000;i++) {}

GPIO_SetBits(GPIOD, GPIO_Pin_13);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_13);
   for(i=0;i<1000000;i++) {}

GPIO_SetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_14);
   for(i=0;i<1000000;i++) {}

GPIO_SetBits(GPIOD, GPIO_Pin_15);
   for(i=0;i<1000000;i++) {}
      GPIO_ResetBits(GPIOD, GPIO_Pin_15);
   for(i=0;i<1000000;i++) {}
      
   }
}помогите пожалуйста.

6 Korvin  
0
Резюмируя всё сказанное. Все, у кого подобная ошибка с не состыковкой микроконтроллера и библиотек, аккуратно выполните первый урок, в котором описывается создание и НАСТРОЙКА проекта.

5 Валерон  
0
Правильно- не указан МК который Вы используете, три часа потратил с похожей ошибкой. Для её решения нужно зайти в Project/Options for Target "Target 1"/C.C++ и в поле Define написать - USE_STDPERIPH_DRIVER (Использовать в Файле stm32f10x.h мк который вы выбрали в программе.)

3 Евгений  
0
Скачал с официального сайта указанную библиотеку.
Сделал все по инструкции с этой страницы
Не компилируется, выдает ошибку "STM32F10x_StdPeriph_Driver\src\stm32f10x_tim.c(2870): error: #20: identifier "TIM_CCER_CC4NP" is undefined "

Что делать и кто виноват?

4 Korvin  
0
У вас подключен не тот .s (startup) файл. У вас StdPeriph использует 4-й таймер, который не описан в startup файле. В ошибке написано так. Попробуйте другой стартап. Кроме того, если вы скачали с www.st.com библиотеку stdPeriph, убедитесь, что скачали именно для вашего МК. Кроме того, вместе с библиотекой идёт подходящая к ней версия CMSIS. Используйте её. разные версии stdPeriph и CMSIS могут не согласовываться.

1 exet  
0
Здравствуйте, хочу поблагодарить Вас за эту статью, всё доходчиво и понятно написано.
Правда я остановился на третьем уроке - не получается закомпилировать этот проект.

в main у меня написано следующее

#include "stm32f10x.h"
#include "stm32f10x_conf.h"

int main(void)
{

}
при компиляции выдает:

Build target 'Target 1'
assembling startup_stm32f10x_md_vl.s...
linking...
Primer 2.axf: Warning: L6304W: Duplicate input file system_stm32f10x.o ignored.
Primer 2.axf: Error: L6218E: Undefined symbol assert_param (referred from misc.o).
Target not created

подскажите пожалуйста

2 Korvin  
0
Извините, не обратил внимания на вопрос сразу.
Судя по ошибке у вас проблема с настройкой stm32f10x.h файла.
Там надо раскомментить строку, относящуюся к вашему микроконтроллеру. Возможно у вас раскомментирована не та строка (не соответствующая вашему МК). Эта ошибка может возникнуть при несоответствии регистров МК в стартап файле. Вернитесь к уроку 1 и проверьте внимательно.

P.S. К сожалению мне не удалось воспроизвести вашу ошибку. Но уверен, что проблема в настройке проекта.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]