STM32 usart и немного RS485

Хочу продолжить тему работы в Кокосе и немножко разобраться усартах.
Некоторое время тому назад ко мне пришла вот такая борда с ебея:
cgi.ebay.com/STM32-Development-Board-STM32F103VCT6-3-2-TFT-LCD-/260775580114?pt=LH_DefaultDomain_0&hash=item3cb76f91d2
на чипе STM32F103VCT6 (примеры шедшие с платой 30мб www.onlinedisk.ru/file/716800/)
Не самое дешевое решение но зато почти все для изучения и быстрого старта есть на борту — в отличие от Дискавери. Выбирал я ее исходя из того что мне очень нужен rs485 и желателен ethernet на enc28j60 (т.к. у меня с ним был маленький опыт -спасибо lifelover). Все, что есть на борту описывать не буду по сцылке на ебей все видно.
В общем начал я ковырять усарты еще на дискавери, но там неудобно нужны ttl преобразователи мне было лень их делать (и я их заказал на ebay т.к. при цене в 3.5$ за usb -ttl своего времени и денег я убю больше) и получив на осцилографе с PA9 некие прямоугольничики я забил на это дело.
Итак вчера наконец то дошли руки до исследования работы усартов на вышеописанной плате на на чипе STM32F103VCT6 — благо разведено на этой плате их аж 3 штуки.

Нашел пару примерчиков естественно везде насован printf (кудаж в усарте безнего :), но лично мне он бесполезен т.к. он работает только со нуль терминированными строками) и в примерах в основном только передача. По этой причине мне пришлось написать простой примерчик который тупо возвращает введеный с hyperterminal символ по RS232 и RS485 + моргает светодиодиками соответствующими порту.
Для инициализации USART необходимо сделать несколько вещей (на примере USART1)

1. Замэпить и затактировать его ноги
GPIO_InitTypeDef  GPIO_InitStructure;
      //USART_InitTypeDef USART_InitStructure;

      /* Enable GPIOA clock                                                   */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);

      /* Configure USART1 Rx (PA10) as input floating                         */
      GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

      /* Configure USART1 Tx (PA9) as alternate function push-pull            */
      GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);


плюс надо не забыть, что для USART3 — RS485 нам необходима нога которой мы будем включать передачу на данной плате это нога PB2, поэтому ее надо тоже вначале программы проинициализировать.

2. Заполнить структуру данных инициализации типа USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate            = 9600;
          USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
          USART_InitStructure.USART_StopBits            = USART_StopBits_1;
          USART_InitStructure.USART_Parity              = USART_Parity_No ;
          USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
          USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;


3. Инициализировать усарт
USART_Init(USART1, &USART_InitStructure);
       	  USART_Cmd(USART1, ENABLE);


Портировав пример с дискавери я получил на usart1 — посылки символов, перешел на usart2 — и компилятор заругался — не забываем что разная периферия висит на разных шинах 2 и 3 усарты — на медленной APB1 шине.
все скомпилировалось и на 2м усарте я получил символы а вот на 3-v усарте — rs485 никак — оказалось на шелкографии перепутаны А и B клеммы… — первый косяк. Перекинул провода и все получил. Надо что нито принять теперь — функция USART_GetFlagStatus (USART3,USART_FLAG_RXNE)!=RESET проверяет не получили ли мы что нитов в буфер. Усарт1,2 нормально 3 -й опять косяк… смотрю осцилогрфом на ноге… оп пошел обмен, убрал осцилограф нету обмена — оказалась видимо плохая пайка перепаял 3485 заработало. В общем получился простой но удобный пример для проверки усартов на данной плате. Конвертер USB-RS485 у меня ICP DAS I-7561. Задержки нужны для того чтобы видно было как моргают светодиоды при обмене -а на RS485 и для того чтобы не обрезался хвост посылке (вообще по уму это делается по другому — но прерывания это следующая для меня тема по STM32, правда пока были какие то косяки типа bad gateway немного раскурил прерывания и собственно выложу RS485 на прерываниях — так как надо)



код для: STM32F103VCT6 (Ну и не забыть как всегда подключить в репозитарии модуль USART)

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_conf.h"


/***************************************************************************//**
 * Declare function prototypes
 ******************************************************************************/
void SetupClock(void);
void SetupUSART1(USART_InitTypeDef USART_InitStructure);
void SetupUSART2(USART_InitTypeDef USART_InitStructure);
void SetupUSART3(USART_InitTypeDef USART_InitStructure);

USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef  GPIO_InitStructure;
void Delay_ms(uint32_t ms);

/***************************************************************************//**
 * @brief  Print symbols via USART1,2,3
 ******************************************************************************/

int main(void)
{

	SetupClock();

     //setting parametrs common for all uarts

          USART_InitStructure.USART_BaudRate            = 9600;
          USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
          USART_InitStructure.USART_StopBits            = USART_StopBits_1;
          USART_InitStructure.USART_Parity              = USART_Parity_No ;
          USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
          USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

   //uarts inints
   SetupUSART1(USART_InitStructure);
   SetupUSART2(USART_InitStructure);
   SetupUSART3(USART_InitStructure);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  /* Configure PB2 as rs485 tx select           */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

  /* Configure PD8,9,10 leds          */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* Output symbols on Hyperterminal using 3 ports 2 rs232 and rs485 */
    while(1)
    {

    	 if (USART_GetFlagStatus  (USART1,USART_FLAG_RXNE)!=RESET )
    	             {
    	    		  GPIO_WriteBit(GPIOD,GPIO_Pin_8,Bit_SET);
    	    		  USART_SendData(USART1,USART_ReceiveData (USART1));
    	    		  Delay_ms(2);
    	    		  GPIO_WriteBit(GPIOD,GPIO_Pin_8,Bit_RESET);
     	             }

    	 if (USART_GetFlagStatus  (USART2,USART_FLAG_RXNE)!=RESET )
    	    	    {
    	    	    GPIO_WriteBit(GPIOD,GPIO_Pin_9,Bit_SET);
    	    	    USART_SendData(USART2,USART_ReceiveData (USART2));
    	    	    Delay_ms(2);
    	    	    GPIO_WriteBit(GPIOD,GPIO_Pin_9,Bit_RESET);
    	    	    }

    	 if (USART_GetFlagStatus  (USART3,USART_FLAG_RXNE)!=RESET )
                   {
    		    	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);
    		    	GPIO_WriteBit(GPIOD,GPIO_Pin_10,Bit_SET);
    		    	USART_SendData(USART3,USART_ReceiveData (USART3));
    		    	Delay_ms(2);
    		    	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET);
    		    	GPIO_WriteBit(GPIOD,GPIO_Pin_10,Bit_RESET);
                   }



    }

}

//*************************************************************************
// Delay
//*************************************************************************
void Delay_ms(uint32_t ms)
{
        volatile uint32_t nCount;
        RCC_ClocksTypeDef RCC_Clocks;
    RCC_GetClocksFreq (&RCC_Clocks);

        nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms;
        for (; nCount!=0; nCount--);
}

/***************************************************************************//**
 * @brief Setup clocks
 ******************************************************************************/
void SetupClock()
{
      RCC_DeInit ();                    /* RCC system reset(for debug purpose)*/
      RCC_HSEConfig (RCC_HSE_ON);       /* Enable HSE                         */

      /* Wait till HSE is ready                                               */
      while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

      RCC_HCLKConfig   (RCC_SYSCLK_Div1);   /* HCLK   = SYSCLK                */
      RCC_PCLK2Config  (RCC_HCLK_Div1);     /* PCLK2  = HCLK                  */
      RCC_PCLK1Config  (RCC_HCLK_Div2);     /* PCLK1  = HCLK/2                */
      RCC_ADCCLKConfig (RCC_PCLK2_Div4);    /* ADCCLK = PCLK2/4               */

      /* PLLCLK = 8MHz * 9 = 72 MHz                                           */
      RCC_PLLConfig (RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

      RCC_PLLCmd (ENABLE);                  /* Enable PLL                     */

      /* Wait till PLL is ready                                               */
      while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

      /* Select PLL as system clock source                                    */
      RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);

      /* Wait till PLL is used as system clock source                         */
      while (RCC_GetSYSCLKSource() != 0x08);

      /* Enable USART1 and GPIOA clock                                        */
   //   RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

}
/***************************************************************************//**
 * @brief Init USART1,2,3
 ******************************************************************************/
void SetupUSART1(USART_InitTypeDef USART_InitStructure)
{
      GPIO_InitTypeDef  GPIO_InitStructure;
      //USART_InitTypeDef USART_InitStructure;

      /* Enable GPIOA clock                                                   */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);

      /* Configure USART1 Rx (PA10) as input floating                         */
      GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

      /* Configure USART1 Tx (PA9) as alternate function push-pull            */
      GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

     	  USART_Init(USART1, &USART_InitStructure);
       	  USART_Cmd(USART1, ENABLE);

}


void SetupUSART2(USART_InitTypeDef USART_InitStructure)
            {
            /* Enable GPIOA clock                                                   */
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

            /* Configure USART2 Rx (PA3) as input floating                         */
            GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
            GPIO_Init(GPIOA, &GPIO_InitStructure);

            /* Configure USART2 Tx (PA2) as alternate function push-pull            */
            GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
            GPIO_Init(GPIOA, &GPIO_InitStructure);
       	    USART_Init(USART2, &USART_InitStructure);
         	USART_Cmd(USART2, ENABLE);

            }

void SetupUSART3(USART_InitTypeDef USART_InitStructure)
                 {
                 /* Enable GPIOB clock                                                   */
                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

                 /* Configure USART3 Rx (PA11) as input floating                         */
                 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
                 GPIO_Init(GPIOB, &GPIO_InitStructure);

                 /* Configure USART3 Tx (PA10) as alternate function push-pull            */
                 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
                 GPIO_Init(GPIOB, &GPIO_InitStructure);

            	  USART_Init(USART3, &USART_InitStructure);
              	  USART_Cmd(USART3, ENABLE);

                 }



з.ы. В качестве прикрепленного файла схема данной платы
  • +2
  • 18 августа 2011, 14:30
  • GYUR22
  • 1
Файлы в топике: Schematic.pdf

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

RSS свернуть / развернуть
достал недавно тот самый дискавери, поставил кокос. довольно непривычно смотреть на то как надо инициализировать периферию и ноги стмки.
и у нас не хватает учебного курса по стм32 «для самых маленьких»
0
После некоторого ковыряния в Кокосе с STM32 привыкаешь — и я больше скажу мне так на данный момент гораздо больше нравиться чем для AVR в регистрах ковыряться. Тут как-то все стройно и логично.
0
с одной стороны да, все логично, девайс->регистр ну и ставим нужные биты
с другой стороны «многа букаф»
+1
Уже бы залудил бы кто-нибудь сей учебный курс, что ли, от самых азов. Что называется — «для чайников». С разжевыванием мельчайших подробностей и нюансов. Я бы даже пивом проставился, честное слово. Ди не даст соврать. :)
0
Читай самые азы для любого МК, для которого есть. AVR курс Ди например. Они везде одинаковы.
0
и на том спасибо…
0
Пытаюсь с самых азов без извращений — т.к. сам начинаю и ищу многие вещи, а примеры везде через жопу в левый глаз.
0
За что и респект, по крайней мере от меня лично! Продолжай рассказывать!
0
Скажите, а как реализовано подключение дисплея на Вашей платке, он через FMCS задействован?, если да, то как, ведь в VCT6 доступны только первые два банка FMCS, для NORa и срама.
0
с дисплеем не разбирался еще честно говоря (мне он пока не сильно интересен взял на будущее).
зы но в демке которая была записана на плате все бодренько графически отображалось и тачскрином управлялось — все как на картинках с ебея
0
там операционка для управления тачскрином.?
0
наверное — с платой шла куча примеров для кейл 4 могу выложить куданито ~30метров
0
Давай, выложи. Посмотрим, что там есть.
0
в начале статьи подцепил ссылку
www.onlinedisk.ru/file/716800/
0
в начале статьи подцепил ссылку
0
… а чем прошиваете?
0
дык на фотке st-link…
0
Унес в коллективный блог
0
щас готовлю про прерывания и примерчик с модбасом
0
Вот туда же его и запихайте :)
0
а как у меня в выборе блока тока личный?
0
Блоги — выбираешь нужный — тыкаешь «подключиться» (вилочка такая). Ждешь пока пожелтеет, вуаля — в выборе появился новый блог.
0
чето туплю… где выбрать блог… все затыкал не вижу
0
-_-'
В меню вверху справочная. Изучи.
0
т.е. если я подключился к STM32 то это =коллективный?
0
Да
0
Если подключился, то при написании поста будет выбор куда писать. В личный или в коллективный. Ну и список коллективных в которых ты состоишь.
0
О, про модбас — это хорошо! На AVRках делал, сейчас подумываю на STM32 попробовать. Буду ждать продолжения.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.