Autor Tema: System Workbech y mis comienzos con ST  (Leído 22642 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #15 en: 31 de Marzo de 2015, 21:26:12 »
Arrancaremos con un simple ejemplo, sin usar librerías, solo lo mínimo indispensable que nos da las CMSIS.
Las CMSIS en ST son parte de la standar peripheral library y nos da un conjunto de defines e inicializaciones como para poder trabajar con los diversos registros.
Para instalar estas librerías debemos crear un nuevo proyecto:

Vamos a File -> New -> C project:



le damos un nombre y elegimos AC6 STM32 MCU Project



Elegimos que nos cree las configuraciones para Release y para Debug



En mi caso elijo que voy a crear un proyecto para la placa NUCLEO 411



En la siguiente pantalla debemos elegir si queremos un proyecto vacío o queremos incluir alguna librería de firmware al proyecto.
En un principio elegimos Standar Peripheral Library y como no la encuentra debemos presionar Download target firmware. Despues de un rato se descargan e instalan las librerías. El resto de las opciones las dejamos como están.

Al finalizar nos quedará algo así:



Bueno, si compilamos el proyecto obtenemos una salida como la siguiente:

Código: [Seleccionar]
21:08:43 **** Incremental Build of configuration Debug for project Prueba01 ****
make all
'Building file: ../src/main.c'
'Invoking: MCU GCC Compiler'
C:\STM_WS\Prueba01\Debug
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -DSTM32F4 -DSTM32 -DNUCLEO_F411RE -DSTM32F411RETx -DDEBUG -DUSE_STDPERIPH_DRIVER -DSTM32F411xE -I"C:/STM_WS/nucleo-f411re_stdperiph_lib" -I"C:/STM_WS/Prueba01/inc" -I"C:/STM_WS/nucleo-f411re_stdperiph_lib/CMSIS/core" -I"C:/STM_WS/nucleo-f411re_stdperiph_lib/CMSIS/device" -I"C:/STM_WS/nucleo-f411re_stdperiph_lib/StdPeriph_Driver/inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"src/main.d" -MT"src/main.d" -o "src/main.o" "../src/main.c"
'Finished building: ../src/main.c'
' '
'Building target: Prueba01.elf'
'Invoking: MCU GCC Linker'
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -L"C:\STM_WS\nucleo-f411re_stdperiph_lib\Debug" -T"C:\STM_WS\Prueba01\LinkerScript.ld" -Wl,-Map=output.map -Wl,--gc-sections -o "Prueba01.elf" @"objects.list"  -lnucleo-f411re_stdperiph_lib
'Finished building target: Prueba01.elf'
' '
make --no-print-directory post-build
'Generating binary and Printing size information:'
arm-none-eabi-objcopy -O binary "Prueba01.elf" "Prueba01.bin" && arm-none-eabi-size "Prueba01.elf"
   text    data     bss     dec     hex filename
   1432    1076    1564    4072     fe8 Prueba01.elf
' '

21:08:45 Build Finished (took 2s.156ms)

Con esto ya tenemos un "ejecutable" para cargar al micro.
Nos vamos a debug e iniciamos una sesion de debug y la pantalla que obtenemos es esta:



Hasta aca todo bien, sin demasiado esfuerzo estamos haciendo debug the un proyecto desde cero.

Ya en la próxima empezaremos a poner algo de código al proyecto.
El documento más importante que tiene cada micro es el reference manual. En el se explican todos los registros, modulos y como funciona, orientado a la programacion. En mi caso es este:
http://www.st.com/web/en/resource/technical/document/reference_manual/DM00119316.pdf
De aquí saldran los registros a tocar para usar el micro.

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #16 en: 31 de Marzo de 2015, 23:45:14 »
Bueno, un último empujon para poder hacer nuestro hola mundo.

Lo primero que quiero comentar es que al crear un proyecto con la std perip lib se nos ha agregado al proyecto 2 librerías. Una es la CMSIS, la cual tiene todos los registros de nuestro micro. Tambien hay funciones de inicializacion y configuracion de reloj.
La forma de incluir las CMSIS es haciendo

Código: [Seleccionar]
#include "stm32f4xx.h"

En el proyecto nuestro se han creado varios archivos aparte del main.c Entre ellos encontramos el startup_stm32f411xe.s el cual es el archivo con el código que se ejecuta al arrancar el micro.
Dentro de ese archivo encontramos:

Código: [Seleccionar]
/**
 * @brief  This is the code that gets called when the processor first
 *          starts execution following a reset event. Only the absolutely
 *          necessary set is performed, after which the application
 *          supplied main() routine is called.
 * @param  None
 * @retval : None
*/

    .section  .text.Reset_Handler
  .weak  Reset_Handler
  .type  Reset_Handler, %function
Reset_Handler: 
  ldr   sp, =_estack    /* set stack pointer */

/* Copy the data segment initializers from flash to SRAM */ 
  movs  r1, #0
  b  LoopCopyDataInit

CopyDataInit:
  ldr  r3, =_sidata
  ldr  r3, [r3, r1]
  str  r3, [r0, r1]
  adds  r1, r1, #4
   
LoopCopyDataInit:
  ldr  r0, =_sdata
  ldr  r3, =_edata
  adds  r2, r0, r1
  cmp  r2, r3
  bcc  CopyDataInit
  ldr  r2, =_sbss
  b  LoopFillZerobss
/* Zero fill the bss segment. */ 
FillZerobss:
  movs  r3, #0
  str  r3, [r2], #4
   
LoopFillZerobss:
  ldr  r3, = _ebss
  cmp  r2, r3
  bcc  FillZerobss

/* Call the clock system intitialization function.*/
  bl  SystemInit   
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr   
.size  Reset_Handler, .-Reset_Handler

Al final del código vemos que se llama a SystemInit y finalmente al main.
SystemInit es una funcion de otro archivo que se ha agregado a nuestro poryecto: system_stm32f4xx.c
En dicha funcion se configura el oscillador principal y se configura la flash y la ram.

O sea que con ese código agregado a nuestro proyecto tenemos lo mínimo indispensable para que el micro arranque y ejecute el main, pero nada mas que eso. Si queremos usar el GPIO deberemos encenderlo, lo mismo con cada modulo que este apagado por defecto.

Bien, concentrémonos en el GPIO entonces.
Si nos vamos al reference manual (p 142 en mi caso) y buscamos el apartado del GPIO veremos que registros tenemos y como se usan.
Lamentablemente este user manual no nos previene de que para usar el GPIO primero debemos habilitar el clock a este. Eso lo vemos en el capítulo 6, específicamente en "6.3.9 RCC AHB1 peripheral clock enable register". En el caso de los user manual de NXP, siempre como primer parte de un capítulo explica lo que hay que preconfigurar para que ese modulo funcione. En ST parece no ser así y es algo malísimo, obligarme a leer todo para descubrir que hay que hacer para que funcione un modulo ufffff!
Bueno, revisando ese registro, vemos que tiene un bit denominado GPIOAEN, que poniendolo en 1 le damos reloj al puerto y que en reset esta en 0.

Bien, las CMSIS deben tener esos registros en algún #define. Y efectivamente así es. En la carpeta device de las CMSIS encontramos el archivo stm32f4xx.h dentro del cual tenemos el registro RCC:
Código: [Seleccionar]
#define RCC                 ((RCC_TypeDef *) RCC_BASE)

la direccion RCC_BASE es:
Código: [Seleccionar]
#define RCC_BASE              (AHB1PERIPH_BASE + 0x3800)
por supuesto en otra parte esta definida la direccion del AHB1

En el reference manual habla de registro RCC AHB1ENR. Esto esta codificado en el archivo stm32f4xx.h como una estructura:

Código: [Seleccionar]
/**
  * @brief Reset and Clock Control
  */

typedef struct
{
  __IO uint32_t CR;            /*!< RCC clock control register,                                  Address offset: 0x00 */
  __IO uint32_t PLLCFGR;       /*!< RCC PLL configuration register,                              Address offset: 0x04 */
  __IO uint32_t CFGR;          /*!< RCC clock configuration register,                            Address offset: 0x08 */
  __IO uint32_t CIR;           /*!< RCC clock interrupt register,                                Address offset: 0x0C */
  __IO uint32_t AHB1RSTR;      /*!< RCC AHB1 peripheral reset register,                          Address offset: 0x10 */
  __IO uint32_t AHB2RSTR;      /*!< RCC AHB2 peripheral reset register,                          Address offset: 0x14 */
  __IO uint32_t AHB3RSTR;      /*!< RCC AHB3 peripheral reset register,                          Address offset: 0x18 */
  uint32_t      RESERVED0;     /*!< Reserved, 0x1C                                                                    */
  __IO uint32_t APB1RSTR;      /*!< RCC APB1 peripheral reset register,                          Address offset: 0x20 */
  __IO uint32_t APB2RSTR;      /*!< RCC APB2 peripheral reset register,                          Address offset: 0x24 */
  uint32_t      RESERVED1[2];  /*!< Reserved, 0x28-0x2C                                                               */
  __IO uint32_t AHB1ENR;       /*!< RCC AHB1 peripheral clock register,                          Address offset: 0x30 */
  __IO uint32_t AHB2ENR;       /*!< RCC AHB2 peripheral clock register,                          Address offset: 0x34 */
  __IO uint32_t AHB3ENR;       /*!< RCC AHB3 peripheral clock register,                          Address offset: 0x38 */
  uint32_t      RESERVED2;     /*!< Reserved, 0x3C                                                                    */
  __IO uint32_t APB1ENR;       /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x40 */
  __IO uint32_t APB2ENR;       /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x44 */
  uint32_t      RESERVED3[2];  /*!< Reserved, 0x48-0x4C                                                               */
  __IO uint32_t AHB1LPENR;     /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */
  __IO uint32_t AHB2LPENR;     /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */
  __IO uint32_t AHB3LPENR;     /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */
  uint32_t      RESERVED4;     /*!< Reserved, 0x5C                                                                    */
  __IO uint32_t APB1LPENR;     /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */
  __IO uint32_t APB2LPENR;     /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */
  uint32_t      RESERVED5[2];  /*!< Reserved, 0x68-0x6C                                                               */
  __IO uint32_t BDCR;          /*!< RCC Backup domain control register,                          Address offset: 0x70 */
  __IO uint32_t CSR;           /*!< RCC clock control & status register,                         Address offset: 0x74 */
  uint32_t      RESERVED6[2];  /*!< Reserved, 0x78-0x7C                                                               */
  __IO uint32_t SSCGR;         /*!< RCC spread spectrum clock generation register,               Address offset: 0x80 */
  __IO uint32_t PLLI2SCFGR;    /*!< RCC PLLI2S configuration register,                           Address offset: 0x84 */
  __IO uint32_t PLLSAICFGR;    /*!< RCC PLLSAI configuration register,                           Address offset: 0x88 */
  __IO uint32_t DCKCFGR;       /*!< RCC Dedicated Clocks configuration register,                 Address offset: 0x8C */

} RCC_TypeDef;

como habran notado, este type_def es el que se uso para definir el RCC, por lo tanto podemos acceder al registro AHB1ENR como un miembro de RCC. Dentro de ese registro tenemos los ditintos bits. Los nombre de cada bit tambien estan definidos:

Código: [Seleccionar]
/********************  Bit definition for RCC_AHB1ENR register  ***************/
#define  RCC_AHB1ENR_GPIOAEN                 ((uint32_t)0x00000001)
#define  RCC_AHB1ENR_GPIOBEN                 ((uint32_t)0x00000002)
#define  RCC_AHB1ENR_GPIOCEN                 ((uint32_t)0x00000004)
#define  RCC_AHB1ENR_GPIODEN                 ((uint32_t)0x00000008)
#define  RCC_AHB1ENR_GPIOEEN                 ((uint32_t)0x00000010)
#define  RCC_AHB1ENR_GPIOFEN                 ((uint32_t)0x00000020)
#define  RCC_AHB1ENR_GPIOGEN                 ((uint32_t)0x00000040)
#define  RCC_AHB1ENR_GPIOHEN                 ((uint32_t)0x00000080)
#define  RCC_AHB1ENR_GPIOIEN                 ((uint32_t)0x00000100)
#define  RCC_AHB1ENR_GPIOJEN                 ((uint32_t)0x00000200)
#define  RCC_AHB1ENR_GPIOKEN                 ((uint32_t)0x00000400)
#define  RCC_AHB1ENR_CRCEN                   ((uint32_t)0x00001000)
#define  RCC_AHB1ENR_BKPSRAMEN               ((uint32_t)0x00040000)
#define  RCC_AHB1ENR_CCMDATARAMEN            ((uint32_t)0x00100000)
#define  RCC_AHB1ENR_DMA1EN                  ((uint32_t)0x00200000)
#define  RCC_AHB1ENR_DMA2EN                  ((uint32_t)0x00400000)
#define  RCC_AHB1ENR_DMA2DEN                 ((uint32_t)0x00800000)
#define  RCC_AHB1ENR_ETHMACEN                ((uint32_t)0x02000000)
#define  RCC_AHB1ENR_ETHMACTXEN              ((uint32_t)0x04000000)
#define  RCC_AHB1ENR_ETHMACRXEN              ((uint32_t)0x08000000)
#define  RCC_AHB1ENR_ETHMACPTPEN             ((uint32_t)0x10000000)
#define  RCC_AHB1ENR_OTGHSEN                 ((uint32_t)0x20000000)
#define  RCC_AHB1ENR_OTGHSULPIEN             ((uint32_t)0x40000000)

Bueno, todo esto es para ponerno en tema y entender la siguiente instruccion:

Código: [Seleccionar]
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

Una vez que el puerto A recibe pulsos de reloj podemos empezar a configrar cada pin. En mi caso tengo un LED conectado al Pin 5 del puerto A.
Si volvemos al apartado GPIO del user manual tenemos:

"GPIO introduction
Each general-purpose I/O port has four 32-bit configuration registers (GPIOx_MODER,
GPIOx_OTYPER, GPIOx_OSPEEDR and GPIOx_PUPDR), two 32-bit data registers
(GPIOx_IDR and GPIOx_ODR), a 32-bit set/reset register (GPIOx_BSRR), a 32-bit locking
register (GPIOx_LCKR) and two 32-bit alternate function selection register (GPIOx_AFRH
and GPIOx_AFRL)."

o sea que nos presenta los registros a usar para manejar los pines como GPIO. Mas abajo tenemos una tabla para ver como configurar cada registro para cada funcion de cada pin.



aqui vemos como configurar el pin como salida, push-pull, sin PU ni PD y con cierta velocidad.

Si seguimos avanzando en el RM vemos el apartado 8.3.3 I/O port control registers con una explicacion adicional de los registro que ya vimos.
Si seguimos adelante vemos el apartado 8.4 GPIO registers que nos va a servir para ver bien los bits a tocar de cada registro.
Vemos que tenemos el registro MODER que se forma por 2 bit para cada pin del puerto con el siguiente significado:
Código: [Seleccionar]
Bits 2y:2y+1 MODERy[1:0]: Port x configuration bits (y = 0..15)
These bits are written by software to configure the I/O direction mode.
00: Input (reset state)
01: General purpose output mode
10: Alternate function mode
11: Analog mode

O sea que debemos cambiar a 01 los bits 10 y 11 del registro GPIOA_MODER para poder poner el pin A5 como salida.
Por supuesto que tenemos las definiciones de los bits:
Código: [Seleccionar]
/******************************************************************************/
/*                                                                            */
/*                            General Purpose I/O                             */
/*                                                                            */
/******************************************************************************/
/******************  Bits definition for GPIO_MODER register  *****************/
#define GPIO_MODER_MODER0                    ((uint32_t)0x00000003)
#define GPIO_MODER_MODER0_0                  ((uint32_t)0x00000001)
#define GPIO_MODER_MODER0_1                  ((uint32_t)0x00000002)

#define GPIO_MODER_MODER1                    ((uint32_t)0x0000000C)
#define GPIO_MODER_MODER1_0                  ((uint32_t)0x00000004)
#define GPIO_MODER_MODER1_1                  ((uint32_t)0x00000008)

#define GPIO_MODER_MODER2                    ((uint32_t)0x00000030)
#define GPIO_MODER_MODER2_0                  ((uint32_t)0x00000010)
#define GPIO_MODER_MODER2_1                  ((uint32_t)0x00000020)

#define GPIO_MODER_MODER3                    ((uint32_t)0x000000C0)
#define GPIO_MODER_MODER3_0                  ((uint32_t)0x00000040)
#define GPIO_MODER_MODER3_1                  ((uint32_t)0x00000080)

#define GPIO_MODER_MODER4                    ((uint32_t)0x00000300)
#define GPIO_MODER_MODER4_0                  ((uint32_t)0x00000100)
#define GPIO_MODER_MODER4_1                  ((uint32_t)0x00000200)

#define GPIO_MODER_MODER5                    ((uint32_t)0x00000C00)
#define GPIO_MODER_MODER5_0                  ((uint32_t)0x00000400)
#define GPIO_MODER_MODER5_1                  ((uint32_t)0x00000800)
todo en el mismo stm32f4xx.h

De este modo, con las siguientes instrucciones:

Código: [Seleccionar]
GPIOA->MODER &= ~GPIO_MODER_MODER5;
GPIOA->MODER |=  GPIO_MODER_MODER5_0;

habilitamos al pin A5 como salida.

luego sigue el registro GPIOA_OTYPER el cual se configura así:
Bits 15:0 OTy: Port x configuration bits (y = 0..15)
These bits are written by software to configure the output type of the I/O port.
0: Output push-pull (reset state)
1: Output open-drain

como lo quiero PP no debo tocar nada.

Luego tenemos GPIOA_OSPEEDR el cual puede tener los siguientes valores:

Bits 2y:2y+1 OSPEEDRy[1:0]: Port x configuration bits (y = 0..15)
These bits are written by software to configure the I/O output speed.
00: Low speed
01: Medium speed
10: Fast speed
11: High speed

como quiero usar el Low speed dejo ese registro sin tocar.

Finalmente tenemos GPIOA_PUPDR el cual puede tomar:

Bits 2y:2y+1 PUPDRy[1:0]: Port x configuration bits (y = 0..15)
These bits are written by software to configure the I/O pull-up or pull-down
00: No pull-up, pull-down
01: Pull-up
10: Pull-down
11: Reserved

Como es salida y no es OD no tiene sentido este registro y lo dejo en 0 sin PU ni PD

Ok, ya tenemos un pin como salida. Tratemos de poner la misma a 1.
Para eso tenemos el 8.4.7 GPIO port bit set/reset register (GPIOx_BSRR) el cual funciona de la siguiente forma:

Bits 31:16 BRy: Port x reset bit y (y = 0..15)
These bits are write-only and can be accessed in word, half-word or byte mode. A read to these bits returns the value 0x0000.
0: No action on the corresponding ODRx bit
1: Resets the corresponding ODRx bit
Note: If both BSx and BRx are set, BSx has priority.
Bits 15:0 BSy: Port x set bit y (y= 0..15)
These bits are write-only and can be accessed in word, half-word or byte mode. A read to these bits returns the value 0x0000.
0: No action on the corresponding ODRx
1: Sets the corresponding ODRx bit

O sea que tenemos los primeros 16 bits para hacer un SET en el pin y los segundos 16 bits para hacer un reset

Con la instruccion
Código: [Seleccionar]
GPIOA->BSRRL = GPIO_BSRR_BS_5;
Encendemos el led, y con
Código: [Seleccionar]
GPIOA->BSRRH = GPIO_BSRR_BS_5;
lo apagamos.

Aqui no hay que hacer uso del |= ya que los ceros que se escriben no afectan a los bits que ya estaban seteados. Solo se setean denuevo los indicados en la nueva instruccion.

Para cambiar el estado de un pin podemos usar el registro GPIOA_ODR el cual contiene los 16 bits del puerto A. El toggle se consigue con
Código: [Seleccionar]
GPIOA->ODR ^= GPIO_BSRR_BS_5;

finalmente para hacer un delay podemos usar:

Código: [Seleccionar]
for(i=0;i<5000000;i++);

Entonces el código de nuestro programa quedará:

Código: [Seleccionar]
#include "stm32f4xx.h"

int main(void)
{
int i=0;

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

GPIOA->MODER &= ~GPIO_MODER_MODER5;
GPIOA->MODER |=  GPIO_MODER_MODER5_0;

GPIOA->BSRRL = GPIO_BSRR_BS_5;

while (1)
{
GPIOA->ODR ^= GPIO_BSRR_BS_5;;
for(i=0;i<5000000;i++);
}
}

bueno, la prueba del funcionamiento:


Primero voy ejecutando paso a paso hasta que el LED se enciende. Luego lo dejo correr libremente.

En la próxima veremos como se simplifica, o no, usando las standar librery para finalmente pasar a HAL o lo que se conoce como STM Cube (no MX)

Saludos!
-
Leonardo Garberoglio

Desconectado xiran

  • PIC16
  • ***
  • Mensajes: 100
Re: System Workbech y mis comienzos con ST
« Respuesta #17 en: 01 de Abril de 2015, 23:39:14 »
Valla q ha estado muy bueno elgarbe, como super novato, me quedo con las guias de este post!

Desconectado cristian_elect

  • PIC18
  • ****
  • Mensajes: 453
Re: System Workbech y mis comienzos con ST
« Respuesta #18 en: 02 de Abril de 2015, 12:30:29 »
Del modo convencional de configuración, viendo los pdfs stm32xxx.h se reduce mucho el código generado, así que los arm con poca memoria salen bien. Hay métodos extra para ganar más espacio y velocidad.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #19 en: 02 de Abril de 2015, 13:13:00 »
Algo que no me cierra es el tamaño del objeto creado:

make --no-print-directory post-build
'Generating binary and Printing size information:'
arm-none-eabi-objcopy -O binary "Prueba01.elf" "Prueba01.bin" && arm-none-eabi-size "Prueba01.elf"
   text      data       bss       dec       hex   filename
   1172      1076      1564      3812       ee4   Prueba01.elf

Aqui tenemos una explicacion de los numero:
http://www.todopic.com.ar/foros/index.php?topic=42355.0

El caso anterior es con la optimizacion para reducir el código.

me parece muy grande el código generado para las lineas que hemos programado. Seguramente hay funciones que no se utilizan, por ejemplo tenemos el syscalls.c que no estoy seguro si se usa para algo o no...

Esto lo pongo acá, porque estoy seguro que si creamos un programa con el Cube MX seguramente el código será gigantezco y por mas que pongamos la optimizacion, esta no hace magia. Si tenemos un .c lleno de funciones, de las cuales solo usamos 1 pues el optimizador no creo que elimine las que no se usan...

Seguiré investigando esto y ya veremo el nuevo ejemplo con las std perip lib.

Saludos
-
Leonardo Garberoglio

Desconectado cristian_elect

  • PIC18
  • ****
  • Mensajes: 453
Re: System Workbech y mis comienzos con ST
« Respuesta #20 en: 02 de Abril de 2015, 15:04:41 »
En keil sale 724B sin optimizar y 620B optimizando.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #21 en: 02 de Abril de 2015, 20:47:57 »
Las std perip library son las antiguas librerías de periféricos de STM, ahora reemplazadas por las HAL del STM32Cube. Las mismas se encuentran en el mismo proyecto que se agregó a nuestro workspace al crear el primer proyecto:



Lo que nos dan esas librerías son funciones para abstraer un poco los registros y darnos una capa de abstaracion del hardware (HAL). Están organizadas por periférico y tenemos, por ejemplo, los archivos stm32f4xx_gpio.h y stm32f4xx_gpio.c para el manejo del GPIO (gen purpose IO).

En el .h vemos un monton de definiciones, estructuras y typedef que nos permitirán manejar el gpio de forma "sencilla". Pongo entre comillas porque, a mi entender, hay periféricos donde el tiempo de estudio del .h junto al .c para aprender a usar las librerías propuestas es muy similar al de estudiar directamente el REFERENCE MANUAL y ver como funciona el periférico directamente.

Dentro del .h encontramos:

Código: [Seleccionar]
/**
  * @brief   GPIO Init structure definition  
  */
typedef struct
{
  uint32_t GPIO_Pin;              /*!< Specifies the GPIO pins to be configured.
                                       This parameter can be any value of @ref GPIO_pins_define */

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

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

  GPIOOType_TypeDef GPIO_OType;   /*!< Specifies the operating output type for the selected pins.
                                       This parameter can be a value of @ref GPIOOType_TypeDef */

  GPIOPuPd_TypeDef GPIO_PuPd;     /*!< Specifies the operating Pull-up/Pull down for the selected pins.
                                       This parameter can be a value of @ref GPIOPuPd_TypeDef */
}GPIO_InitTypeDef;

tambien vemos como funciones interesantes:

Código: [Seleccionar]
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

entre otras.

En el archivo stm32f4xx_gpio.c tenemos la implementacion y ayuda de uso de estas funciones:

Veamos primero GPIO_Init:

Código: [Seleccionar]
/**
  * @brief  Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F405xx/407xx and STM32F415xx/417xx devices
  *                      x can be (A..I) to select the GPIO peripheral for STM32F42xxx/43xxx devices.
  *                      x can be (A, B, C, D and H) to select the GPIO peripheral for STM32F401xx devices.  
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
  uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
...
...
...
}

Como dice el título inicializa un puerto determinado conforme a la estructura pasada. La estructura con la inicializacion del puerto es del tipo GPIO_InitStruct que vimos unas lineas mas arriba.

La otra funcion es.

Código: [Seleccionar]
/**
  * @brief  Toggles the specified GPIO pins..
  * @param  GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F405xx/407xx and STM32F415xx/417xx devices
  *                      x can be (A..I) to select the GPIO peripheral for STM32F42xxx/43xxx devices.
  *                      x can be (A, B, C, D and H) to select the GPIO peripheral for STM32F401xx devices.
  * @param  GPIO_Pin: Specifies the pins to be toggled.
  * @retval None
  */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  GPIOx->ODR ^= GPIO_Pin;
}

En este caso, para invertir el estado de un pin tenemos que pasarle a la funcion el puerto en cuestion y el pin.

Con esta librería hemos resuelto las funciones sobre el GPIO. Lo que nos esta faltando es poder habilitar el reloj al puerto que queremos usar. Eso debería estar en GPIO_Init, pero no lo está.
Para estas cuestiones tenemos otra librería llamada stm32f4xx_rcc.h y stm32f4xx_rcc.c. En esa librería podemos encontrar una funcion llamada  RCC_AHB1PeriphClockCmd, la cual permite habilitar o deshabilitar el clock a algun periférico del AHB1.

Bien, conn esas 3 instrucciones podemos armar nuestro hola mundo.
El programa quedaría así:

Código: [Seleccionar]
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"

int main(void){
GPIO_InitTypeDef GPIO_InitStruct;
int i=0;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA, &GPIO_InitStruct);


while(1){
GPIO_ToggleBits(GPIOA, GPIO_Pin_5);
for(i=0;i<5000000;i++);
}
}

Primero tenemos los Includes para poder hacer uso de los registros y funciones del RCC y del GPIO.
Luego tenemos 2 variables, una es del tipo GPIO_Init. En dicha estructura debemos configurar cada miembro para especificar que el pin será Salida, PP, sin PU ni PD, trabajara a baja frecuencia y de qué pin estamos hablando. Luego hacemos la llamada a la funcion que inicializa o configura el GPIO en cuestion.

Finalmente, en el bucle infinito hacemos uso de la funcion ToggleBits y el delay del lazo for.

En este caso la compilacion arroja:

arm-none-eabi-objcopy -O binary "Prueba02.elf" "Prueba02.bin" && arm-none-eabi-size "Prueba02.elf"
   text      data       bss       dec       hex   filename
   1340      1076      1564      3980       f8c   Prueba02.elf

Se nota un pequeño incremento del tamaño de la flash.

El uso de librerías, en este caso las std periph lib nos permite independizarnos de andar mirando el reference manual hasta cierto punto, pero nos obliga a leernos la documentacion de las librerías para ver que hace cada una, que hay que pasarle como parámetro, ver las enumeraciones, los #define, etc. Por otra parte debemos conocer algo del funcionamiento del micro, de otro modo, nunca hubiesemos savido que necesitabamos buscar algo referido al RCC que nos permita darle clock al puerto que queremos usar...
Seguramente en un nivel más alto o con vistas a portabilidad entre micros, la cosa tire mas para el lado de las librerías.

Como paso siguiente debemos ver que pasa con las nuevas librerías de ST, las STM32FxxCube para finalmente pasar al generador de código Cube MX

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #22 en: 04 de Abril de 2015, 18:57:47 »
Bien, estuve leyendo y leyendo y probando una cosa y la otra. He estado programando algunas cosas simples con las std perip library y si bien cuesta un poco acostumbrarse a su uso, terminó funcionando bien. El tema es notar que se hace uso de estructuras que se deben llenar con los parámetro y luego llamar a las distintas funiones. Por ejemplo para usar el timer:

Código: [Seleccionar]
// Config Base time for TIM5
TIM_TimeBaseInitTypeDef timerInitStructure;
// Shooting for 0.5 MHz, (2us) so we will count from 2000 to 4000
// when input goes from 1mseg to 2mseg
timerInitStructure.TIM_Prescaler =  (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1);
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0xFFFF;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM5, &timerInitStructure);

una vez que nos acostumbramos a usar de esa forma las funciones pues las cosas van más fáciles.

Bien, con eso mas o menos dominado (mas menos que mas) pasemos a las famosas Cube o HAL usando directamente el generador de código Cube MX.

Para la instalacion, simplemente sigamos estos pasos:
ir a http://www.st.com/web/en/catalog/tools/PF257931 y descargar STSW-STM32095.zip
Dentro de eclipse ir a help->install new software luego en Add -> archive y buscamos el zip anterior damos Ok y vamos completando los pasos hasta terminar.

Para crear un nuevo proyecto usando el Cube MX iremos a Windos->Open perspective-> Other


Luego elegimos SMT32Cube MX y nos aparecerá la pantalla principal:



Ahi elegimos New Project

En la nueva ventana debemos elegir entre un micro puntual o una placa. En mi caso eligo una placa ya que voy a trabajar con la nucelo 411:



Le damos Ok y ahora tenemos una imagen de nuestro micro con algunas configuraciones ya establecidad (por ser propias de la placa):



Aqui debemos notar que lo que esta en rojo son funciones que no se pueden usar por estar el pin elegido para otra funcion.
Eligo los pines PA0 a PA3 como Canales 1 a 4 del TIM5. Los voy a usar como Input Capture para leer una señales tipo PWM.
Tambien configuro PA11 y 12 como UART6:



Para terminar la configuracion de los pines debemos activar el periférico en la parte izquierda.
Entonces busco UART6 y eligo ASYNCHRONOUS
Tambien abro el TIM5 y configuro todo lo necesario

La segunda pestaña, la de configuracion de reloj la dejo como está, ya que es la por defecto de la placa NUCLEO 411 y sirve para la 401 tmb.
En la tercer pestaña, configuration veo que me aparecen los modulos configurados anteriormente:



Si elijo el TIM5 se me abre una gran ventana llena de configuraciones:



Bueno, voy configurando todo lo que respecta al timer, luego al uart6. Algo interesante que despues veremos como queda es esta pantalla:



donde podemos asignar un label a un pin del micro, en este caso le puse IC1_PIN al PA.0

Finalmente vamos a generar codigo y configuramos como en la siguiente figura:




Para guardar el proyecto he elegido una carpeta vacía que usaremos como WorkSpace.
No estoy seguro de cuán integrado esté el CubeMX con eclipse, porque aunque lo pueda ejecutar dentro de eclipse, al momento de abrir el proyecto generado debemos recurrir a la importacion ya que no se nos agrega al worksapce. Por ahora no he encontrado informacion sobre este punto. Lo que si hay en OpenSTM es una guía de importacion donde se marcan algunos problemas que hay entre lo generado por el Cube MX y lo que se abre en Eclipse:
http://www.openstm32.org/Importing+a+STCubeMX+generated+project

Bien, siguiendo esos paso hacemos la importacion.
Al finalizar damos a Build All y obtenemos nuestro programa compilado.



Ahora es cuestion de revisar un poco lo generado y agregar nuestro código.

Eso en la próxima!

Pero antes una conclusion de los últimos días en los que he estado trabajando bastante con el 32F411, no tanto programando sino investigando y aprendiendo. Estos micros ya no son tan simples como un M0 o hasta un M3, este micro que estoy usando, por lo menos es bastante mas complejo, los timer tienen funciones muy avanzadas por ejemplo y lleva mucho tiempo de lectura, no solo del user manual, sino de las librerías a usar. Es por ello que le doy un poquito más de crédito al CubeMX, que no me gustaba para nada y al querer usar las HAL veo que se hace casi impresindible su uso. Con las std perip lib me animo a seguir avanzando con el resto de los perifericos y hacerlos funcionar, hay mucha info, mucos ejemplos, etc. Pero con las HAL la cosa cambio mucho, hay mucha mas abstraccion y la cosa ya no es tan intuitiva, entonces el CubeMX es una buena herramienta.

sds.

-
Leonardo Garberoglio

Desconectado cristian_elect

  • PIC18
  • ****
  • Mensajes: 453
Re: System Workbech y mis comienzos con ST
« Respuesta #23 en: 04 de Abril de 2015, 23:47:59 »
Los pdf de los micros Stm32 no te dan ejemplos básicos de configuración como lo hace Atmel en C y ASM. También STM8 tampoco te dan ejemplos básicos en sus pdf de los micros. Eso es lo malo de ST pero el precio lo compensa hay que buscar codigos para configurar estos micros.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #24 en: 05 de Abril de 2015, 00:31:52 »
Yo no puedo creer que la tabla con los pines y las funciones alternativas de cada uno no esté en el reference manual!!!!!! Esta en una especie de datasheet, donde se encuentran los datos eléctricos del micro. Para que mierda quiero ahi las funciones alternativas de cada pin???? esa tabla la uso con el manual de programacion!!!!

El post anterior fue a las 7 de la tarde, desde entonces corté 40 mintos para comer y recien a las 12:00 pude hacer funcionar el código generado por el CubeMX. Y solo pretendo usar un timer con 1 canal de Captura!!!!!!!!!!!!!!!! Hay código repetido, falta código fundamental, el código generado configura el timer y las IC, enciende el timer pero no enciende las IC!!!!!!!! ensima no hay un pu...t.... lugar donde te digan cual de las 100 funciones y las 300 macros que trae el archivo del timer hay que usar.
Quizá piensen que estoy exagerando. Miren lo que es el driver del timer. adjunto el .c y el .h es para enloquecerse!!!!!!

Usar las Cube/hal sin el generador MX es imposible, no hay ejemplos casi, solo algo de como configurar algunas cosas muy básicas.
Usar el generado de codigo no asegura que las cosas funcionen, hay que revisar todo el codigo generado y buscar que cosas andan y que cosas no.

Mira que divertido como hay que manejar la interrupcion del timer, el generador de codigo te crea un archivo llamado stm32f4xx_it.c que contiene esto:

Código: [Seleccionar]
/**
* @brief This function handles TIM5 global interrupt.
*/
void TIM5_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim5);
}

bien!!! me paro arriba de HAL_TIM_IRQHandler apreto F3 y me lleva al gigantezco driver del TIMER stm32f4xx_hal_tim.c especificamente acá:

Código: [Seleccionar]
/**
  * @brief  This function handles TIM interrupts requests.
  * @param  htim: pointer to a TIM_HandleTypeDef structure that contains
  *                the configuration information for TIM module.
  * @retval None
  */
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
  /* Capture compare 1 event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)
    {
      {
        __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
       
        /* Input capture event */
        if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00)
        {
          HAL_TIM_IC_CaptureCallback(htim);
        }
        /* Output compare event */
        else
        {
          HAL_TIM_OC_DelayElapsedCallback(htim);
          HAL_TIM_PWM_PulseFinishedCallback(htim);
        }
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
      }
    }
  }
  /* Capture compare 2 event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
      /* Input capture event */
      if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00)
      {         
        HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* Capture compare 3 event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
      /* Input capture event */
      if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00)
      {         
        HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* Capture compare 4 event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
      /* Input capture event */
      if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00)
      {         
        HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* TIM Update event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
      HAL_TIM_PeriodElapsedCallback(htim);
    }
  }
  /* TIM Break input event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
      HAL_TIMEx_BreakCallback(htim);
    }
  }
  /* TIM Trigger detection event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
      HAL_TIM_TriggerCallback(htim);
    }
  }
  /* TIM commutation event */
  if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
  {
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
      HAL_TIMEx_CommutationCallback(htim);
    }
  }
}

faaaaaaaaaaaaaa en una sola funcion se verifican todas las fuentes de interrupcion del timer!!!! que idolos! y si quiero usar una sola fuente de interrupcion??? bue, un poco mas de codigo no le hace mal a nadie, total es "genérico" para cualquier sistema...

Bueno, pero mi código de lo que debo hacer cuando entra IC del canal 1 donde lo meto???? en ese archivo no puedo porque es parte del driver HAL del timer.... mmmm.... piensa piensa piensa.... Veo la funcion y despues de 3 if, cuando se da cuenta que es una int por el canal 1 del IC llama a HAL_TIM_IC_CaptureCallback(htim)
Me paro arriba, apreto F3 y nada!, no existe. busco en google, nada!! empiezo a mirar todo el maldito stm32f4xx_hal_tim.c y cuando voy por la línea 4270 veo:

Código: [Seleccionar]
/**
  * @brief  Input Capture callback in non blocking mode
  * @param  htim: pointer to a TIM_HandleTypeDef structure that contains
  *                the configuration information for TIM module.
  * @retval None
  */
__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_IC_CaptureCallback could be implemented in the user file
   */
}

bueno!!!! ahi esta!!! tengo que implementar la funcion __HAL_TIM_IC_CaptureCallback en mi archivo, entonces my archivo de ISRs queda así

Código: [Seleccionar]
/**
* @brief This function handles TIM5 global interrupt.
*/
void TIM5_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim5);
}

/* USER CODE BEGIN 1 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
uint16_t time = 0;

//Get the Captured timer
time = HAL_TIM_ReadCapturedValue(&htim5, TIM_CHANNEL_1);
//Check if it it Rising edge
if(GPIOA->IDR & (1 << 0)){
//Reset de timer on Rising Edge. This way avoid overflow problem
//ie: previous capture were 65000 current capture is 23 so 23-65000 -> overflow
__HAL_TIM_SET_COUNTER(&htim5, 0 );
}else{ //falling edge
//Return captured timer
IC1Capture = time;
}
}

primero entra a TIM5_IRQHandler de ahi se va a HAL_TIM_IRQHandler y de ahi vuelvo a este archivo a HAL_TIM_IC_CaptureCallback WTF!!!!!

Cuando termino eso y veo que sigue sin andar me quiero morir. 1 hora más para descubrir que no se ha arrancado las IC, estan configuradas, pero no arrancan a funcionar hasta llamar a una funcion, que dicho sea de paso, la descubri mirando el driver del timer, funcion por funcion!!!!

Conclusion.... un desatre!!!!!!
-
Leonardo Garberoglio

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re: System Workbech y mis comienzos con ST
« Respuesta #25 en: 05 de Abril de 2015, 07:20:41 »
Citar
pero el precio lo compensa hay que buscar codigos para configurar estos micros.

cuidado con eso cristian, en mi empresa utilizabamos ST para algunos desarrollos precisamente por lo barato, y tuvimos que cambiarlo precisamente por el tiempo que se tardaba en hacer cualquier tonteria ademas de los fallos rarisimos que tenia.

ese tiempo de desarrollo cuesta muchisisisisiisismo dinero.

« Última modificación: 05 de Abril de 2015, 08:18:03 por juaperser1 »

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re: System Workbech y mis comienzos con ST
« Respuesta #26 en: 05 de Abril de 2015, 08:20:11 »
Citar
Yo no puedo creer que la tabla con los pines y las funciones alternativas de cada uno no esté en el reference manual!!!!!! Esta en una especie de datasheet, donde se encuentran los datos eléctricos del micro. Para que mierda quiero ahi las funciones alternativas de cada pin???? esa tabla la uso con el manual de programacion!!!!

Eso es lo que te puse en el otro post de que esta todo desperdigado por diferentes hojas  :? :?

Desconectado xiran

  • PIC16
  • ***
  • Mensajes: 100
Re: System Workbech y mis comienzos con ST
« Respuesta #27 en: 11 de Abril de 2015, 02:31:42 »
Gracias a elgarbe, pude lograr hacer ese hola mundo con la tarjeta discovery stm32f0, pego el codigo, por si le sirve a alguien, lo q hace, es prender los 2 unicos leds q trae la placa, alternandolos, pero no usando la funcion q togglea los pines:

int main(void) {
   int i=0;
   //Aqui le doy clock al puerto C
   RCC->AHBENR |= RCC_AHBENR_GPIOCEN;

   //Aqui pongo en modo salida el pin c8
   GPIOC->MODER &= ~GPIO_MODER_MODER8;
   GPIOC->MODER |= GPIO_MODER_MODER8_0;

   //Aqui pongo en modo salida el pin c9
   GPIOC->MODER &= ~GPIO_MODER_MODER9;
   GPIOC->MODER |= GPIO_MODER_MODER9_0;

   while (1) {
      GPIOC->BSRR |=  GPIO_BSRR_BS_8;//Aqui pongo en 1 al pin C8
      GPIOC->BSRR |=  GPIO_BSRR_BR_9;//Aqui pongo en 0 al pin C9
      for (i = 0; i < 500000; i++);

      GPIOC->BSRR |=  GPIO_BSRR_BR_8;//Aqui pongo en 0 al pin C8
      GPIOC->BSRR |=  GPIO_BSRR_BS_9;//Aqui pongo en 1 al pin C9
      for (i = 0; i < 500000; i++);
   }
}

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re: System Workbech y mis comienzos con ST
« Respuesta #28 en: 11 de Abril de 2015, 09:41:26 »
Muy bien ahí!
Si me hago un tiempito, ahora a la tarde voy a subir el ejemplo para, por medio de CubeMX, hacer el hola mundo con las HAL.

Sds.
-
Leonardo Garberoglio

Desconectado cristian_elect

  • PIC18
  • ****
  • Mensajes: 453
Re: System Workbech y mis comienzos con ST
« Respuesta #29 en: 11 de Abril de 2015, 11:17:44 »
Tengo problemas con openocd, si alguien me dice la configuración para depurar con el stlink.
Últimamente aquí en el foro el interés por los stm32 a subido antes los usaba solo algunas cosas y solo programaba para eso, ahora lo estoy viendo en forma más profunda y haciendo prueba de todas sus funciones. Aquí una página que hay muchos ejemplos y que me sirve de mucho.

http://hotboards.org/index.php/es/blog

Lo que le falta a esta página lo estoy buscando y creando ejemplos y lo sacare sí que faltase en el foro.
« Última modificación: 11 de Abril de 2015, 11:27:00 por cristian_elect »


 

anything