LusoRobótica - Robótica em Português

Sistemas específicos => ARM => Tópico iniciado por: dio123 em 20 de Fevereiro de 2020, 12:58

Título: STM32 inicio
Enviado por: dio123 em 20 de Fevereiro de 2020, 12:58
bom dia,
Mandei vir do ebay um  STM32F103C8T6 bluepill e um st-link v2, para experimentar e conhecer um pouco as coisas.

Acontece que o stm32 veio, já o st-link v2 mudou-se pelo o caminho e chegou stc autoprogrammer usb-ttl que apesar fisicamente serem iguais, os pinos sao diferentes e nao tenho onde ligar SWIO e SWCLK .

Supostamente no lugar  SWIO e SWCLK tenho TCK e RST.



Título: Re: STM32 inicio
Enviado por: jm_araujo em 20 de Fevereiro de 2020, 15:41
Esquece, nada que ver um com o outro.
O STC é basicamente um conversor USB-série, o st-link tem um micro que trata da interface com o micro (inclusive dá para outros fins, tipo converter noutros "dispositivos", como o Black Magic Probe: https://microcontrollerelectronics.com/how-to-convert-an-stm32f103c8t6-into-a-black-magic-probe/  ou j-link: https://www.embarcados.com.br/convertendo-st-link-em-um-j-link/, interfaces JTAG mais genéricas.
Título: Re: STM32 inicio
Enviado por: dio123 em 21 de Fevereiro de 2020, 09:49
Já vi que fui enganado, no entanto ja reclamei no ebay.
 
Então por agora, sem um st-link nao vou conseguir usar o STM32CubeIDE ou STM32CubeProgrammer, para fazer upload certo?.

 
Título: Re: STM32 inicio
Enviado por: dio123 em 06 de Março de 2020, 18:33
Boa tarde,
Após uma luta, consegui o reembolso e mandei  vir outro vendedor o st-link, até paguei mais para vir espanha.

No entanto estou aqui com um problema, e pelo o que li o stm32f103 ser fake.
Ora no  STM32CubeIDE  fiz o projecto do blink tudo  compila sem erros, tudo lindo mas na hora de fazer upload dá-me erro.

Procurei no google pelo erro  conclusão, no STM32CubeIDE  verifica se os stm são verdadeiros.
abri STM32CubeProgrammer peguei o ficheiro upload e o led pisca sem problemas.

Ou seja vim pedir ajuda para que compilador usar e que consiga fazer debugger no stm?
Da vossa experiência o que se recomenda.



Título: Re: STM32 inicio
Enviado por: dio123 em 24 de Março de 2020, 18:00
Depois de ter dado aqui umas voltas, acabei por comprar outra bluepill  mas desta vez genuino, no qual ja funciona o ide studio.
Andei a mexer em vários programas e acho que vou pelo o  Keil uVision5.

No entanto ando aqui a fazer uns testes com piscar leds, pwm e agora chegou a vez de  meter o  bma180 accelerometer a falar stm32.

Sorte ou azar já estive hoje o dia todo virar o google  e não apanhei nenhum exemplo, tentei pegar nuns exemplos mas sem sucesso.

Então a ideia seria arranjar uma lib mais parecida possivel com a wire do arduino e depois partir daqui.

Título: Re: STM32 inicio
Enviado por: senso em 24 de Março de 2020, 18:23
Porque não usar o TrueStudio(antigo attolic) que é 100% gratuito(pelo menos, antes tudo o que era Keil era pago, versão free estava limitada a 32Kb de código compilado, para além de ter alguma sintaxe diferente do gcc), juntas ao CubeMX para gerar código para os periféricos, e partes dai, aliás ao que parece já é um tudo em um chamado STM32CubeIDE:
https://www.st.com/en/development-tools/stm32cubeide.html

Tambem tens o platformio que suporta N dev boards nativamente, para um ambiente mais simplificado:
https://platformio.org/

Se o BMA estiver a falar i2c, é começar com fazer uma função de scan do bus i2c, assim ficas logo a saber se ele está no bus ou não, e em que endereço anda, dai para a frente, é ler meia duzia de registos e escrever para mais uns quantos, não diria que é preciso uma biblioteca, mas se assim o preferes, bma180 github e tens N projectos com código, trocas as funções de read e write pelas do stm e siga.

Tens aqui um exemplo, só tens de alterar os write e read para as funções que o STM32 usa para falar i2c:
https://github.com/PaulStoffregen/FreeIMU_original/blob/master/libraries/bma180/bma180.cpp

Título: Re: STM32 inicio
Enviado por: dio123 em 09 de Abril de 2020, 10:48
Bom dia,
Ando as uns dias a explorar o stm32 e já consegui meter bma180 a falar com stm32, já criei o código iniciação, já leio o chip id , consigo confirmar o device adress.

No entanto estou com um problema de interpretação dos valores,e tem haver com a maneira que obtenho  os dados.
Vou-me explicar da melhor forma.

No arduino  tenho:
int n=6;
byte result[5];
readFrom(BMA180, 0x02, n , result);
int x= (( result[0] | result[1]<<8)>>2)+offx ;
float x1=x/4096.0;

Onde o result[0] = x-lsb  result[1] x-msb  result[2] = y-lsb  result[3] y-msb

No stm32 tenho: HAL_I2C_Mem_Read (&hi2c1, (uint16_t) (BMA180 << 1) , (uint16_t) (DATA<< 2)  , 2, READXYZ,8, HAL_MAX_DELAY);

Aqui o que acontece é que é READXYZ[0] = chip-id  READXYZ[1]-version bma READXYZ[2]x-lsb READXYZ[3]x-msb READXYZ[4]y-lsb READXYZ[5]y-msb
Até aqui tudo bem le-me 8 regsitos o ultimo é temperatura ,  como está no datasheet.

Agora ao interpretar para obter o x, pensava que bastava mudar a posição do array,para as correctas mas não,  está-me a dar x1=3.2g
int x= (( READXYZ[2] | READXYZ[3]<<8)>>2)+offx ;
float x1=x/4096.0;

A minha duvida é se o problema não terá haver com Bitwise operation  READXYZ[3<<8)>>2 no qual terei de ajustar uma vez que o tamanho do array é diferente, e para vos ser sinceros  não estou a ver como saber os valores que colocar.
E acho que é aqui que perciso de ajuda.

Título: Re: STM32 inicio
Enviado por: KammutierSpule em 09 de Abril de 2020, 11:50
tens de formatar melhor o teu post para perceber o codigo.

no STM32 se tiveres debugger podes aceder aos registos e ver o que esta a acontecer byte a byte.
outra alternativa e' se tiveres porta serie, imprimir os valores
exemplo

Código: [Seleccione]
printf("0x%04X", variableInteger)
imprime uma variavel em formato hexadecimal 0xFFFF
assim ja podes analisar byte a byte / bit a bit
Título: Re: STM32 inicio
Enviado por: jm_araujo em 09 de Abril de 2020, 12:20
Manda para fora o READXYZ[2],  READXYZ[3] e o x .
Fica mais fácil de perceber onde está a falhar.
Título: Re: STM32 inicio
Enviado por: dio123 em 09 de Abril de 2020, 23:23
Descobri uma diferença que está a provocar que tenha más leituras, e despistar qualquer codigo criei um novo projecto só com o código abaixo.
Usei um codigo simples e pelo debuuger stm e o arduino.

uint8_t READXYZ[2];
READXYZ[0]=0X61;
READXYZ[1]=0XFF ;
x=( READXYZ[0] | READXYZ[1]<<8); // vai pegar 0x61 e 0xff e escrever para  esquerda

No arduino recebo
x_hex=0xFFFFFF61  x_bin=11111111111111111111111101100001

No stm32 exactamente o mesmo codigo copy/paste recebo
x_hex=0xff61   x_bin=1111111101100001
no me preenche os restantes 4bits ff para a esquerda.
Ainda comparei em binario e é a mesma coisa não coloca os restantes 1 para a esquerda


Título: Re: STM32 inicio
Enviado por: KammutierSpule em 10 de Abril de 2020, 00:36
Nao estou a entender o problema, qual e' o resultado que esperas ter?
Tambem nao da para perceber porque nao estas a formatar o codigo. Tens de usar o formatador do codigo do forum, se nao aparece simbolos como este:  8)

Os bits, podem ser da maneira como o arduino ou stm faz o print.
num esta a assumir unsigned short (16bits) outro esta a assumir unsigned long int (32 bits)
agora porque estao a 0xFFFF nao sei  :(

Uma nota: estas a usar uint8. e a fazer shifts. Nao sei o tipo da variavel x
mas para ter certeza que funciona correctamente, devias converter os bytes para unsigned int.
Pode as vezes a plataforma e o compilador usarem uint8 e nao dar o resultado esperado.

Título: Re: STM32 inicio
Enviado por: Njay em 10 de Abril de 2020, 02:54
Eu prefiro usar os tipos que dizem explicitamente qual o tamanho, não deixa ambiguidade.
O tamanho e sinal do char, int, etc, dependem da plataforma e compilador.

Para mim também não é claro qual é o teu problema, mas se queres shiftar à esquerda uma variável mantendo os bits mais à esquerda, 1º tens que extender o tamanho dessa variável, ou seja, copiá-la para outra maior onde caiba o resultado, e só depois shiftar, a maior.
Por exemplo, se queres shiftar uma variável de 8 bits (val) 4 bits à esquerda mantendo os 4 bits que iriam sair, tens que fazer:

uint8_t   val = ...
uint16_t  val16 = val;
val16 = val16 << 4;


O resultado precisa de 12 bits (8 + 4) e portanto uma variável de 16 serve.
Há outras formas de fazer isto (com casts), esta é a maneira mais descomplicada.

Outra coisa é que os shifts para a direita de valores (variáveis) com sinal introduzem sempre um bit a 1 à esquerda. Chamam-se "deslocamentos aritméticos" e é o comportamento correcto para a divisão de um número, em complemento de 2 (como temos hoje em dia nos CPUs), por uma potência de 2.
Título: Re: STM32 inicio
Enviado por: dio123 em 12 de Abril de 2020, 15:52
Boa tarde,
O codigo colocado na janela do codigo.

O problema é que o resultado obtido na variável final após o deslocamento para a direita  é totalmente diferente entre arduino/avr studio e o stm32. Isto faz com que x1 que é resultado final  o valor correcto é 0.01G e no stm32 da-me 15.69G e o código é exactamente o mesmo.
isto pelo debugger do stm32 variável final é 0xFF61, e o arduino 0xFFFFFF61.

Experimentei o vários tipos de declaração para a variável final mas o resultado é sempre o mesmo.

Código: [Seleccione]
  while (1)
  {
  uint8_t READXYZ[2];
  unsigned long int final;

  READXYZ[0]=0x61;
  READXYZ[1]=0xff;
  final = ( READXYZ[0] | READXYZ[1]<<8);
  float x1=(final/4096.0);

  HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
  HAL_Delay(5000);

}
Título: Re: STM32 inicio
Enviado por: KammutierSpule em 12 de Abril de 2020, 16:51
Experimenta assim:
Código: [Seleccione]
   uint8_t READXYZ[2];
   uint32_t final;

   READXYZ[0]=0x61;
   READXYZ[1]=0xff;
   final = ( (uint32_t)READXYZ[0] | (uint32_t)READXYZ[1] << 8);
   float x1=( (float)final / 4096.0f );

Ou com isto:

Código: [Seleccione]
   final = (( (uint32_t)READXYZ[0] | (uint32_t)READXYZ[1] << 8)) & 0xFFFF;
Título: Re: STM32 inicio
Enviado por: dio123 em 12 de Abril de 2020, 17:05
Boa tarde,
Desde já agradeço pela ajuda.

Experimentei os exemplos que enviou no entanto o resultado em ambos é o mesmo:
Hex:0xff61   Binary:1111111101100001

Título: Re: STM32 inicio
Enviado por: KammutierSpule em 12 de Abril de 2020, 17:16
Experimentei os exemplos que enviou no entanto o resultado em ambos é o mesmo:
Hex:0xff61   Binary:1111111101100001

Optimo, era isso que esperava que desse. Qual e' entao o problema ? :)
Título: Re: STM32 inicio
Enviado por: jm_araujo em 12 de Abril de 2020, 18:03
Andam lá perto mas não atinam ;)
Testa isto assim:
Código: [Seleccione]
   uint8_t READXYZ[2];
   int16_t final;

   READXYZ[0]=0x61;
   READXYZ[1]=0xff;
   final = READXYZ[0] | READXYZ[1] << 8;
   float x1=(final / 4096.0f );


Lógica: o que o arduino está a fazer é "esticar" o sinal de um número de 16 bits (0xff61) para 32 bits. Nesse caso queremos que variável para meter os 2 bytes seja um  "signed" de 16 bits, para garantir que ao fazer as promoções para as contas o C entenda corretamente o sinais. Removi os casts todos porque para operações matematicas não devem ser necessários se estiver bem escrito (senão nunca mais se saía do lugar a programar em C)
Título: Re: STM32 inicio
Enviado por: dio123 em 12 de Abril de 2020, 20:20
Boa tarde,
jm_araujo - é isso mesmo, assim já consegui fazer a leitura correcta e obter os valores de x,y,z certinhos.

Agradeço a todos pela ajuda

Título: Re: STM32 inicio
Enviado por: Njay em 12 de Abril de 2020, 21:45
Lógica: o que o arduino está a fazer é "esticar" o sinal de um número de 16 bits (0xff61) para 32 bits.

Chama-se "estender o sinal". Alguns CPUs, se não todos, têm uma instrução para isso.

Quando copiamos de uma variável para outra maior com sinal, os bits mais significativos têm que ser iguais ao mais significativo da variável pequena, senão o sinal do número não é mantido. Por exemplo, passar -1 em 8 bits para -1 em 16 bits; se apenas copiarmos os 8 para os 8 menos significativos dos 16 com sinal, ficamos com 0x00ff, que não é -1 mas sim 255. O correcto é passar para 0xffff, que é -1 em 16 bits. A regra que faz a conversão correcta é pegar no bit mais significativo da variável pequena e replicá-lo pelos bits mais significativos da variável maior (estender o sinal):

-1 (8bits) = 1111 1111b -> 0000 0000 1111 1111b
mas o bit mais significativo é 1 e portanto repete-se nos restantes bits à esquerda
1111 1111 1111 1111b (16bits) = -1

Já se o valor original fosse 1 (ou qualquer valor positivo, que tem o bit mais significativo = 0), repetia-se 0 e o resultado final continua a ser 1
1 (8bits) = 0000 0001b -> 0000 0000 0000 0001b (16bits)

Em variáveis sem sinal, não se estende o sinal, os bits "novos", mais significativos do sinal, ficam sempre a zero.
Título: Re: STM32 inicio
Enviado por: KammutierSpule em 12 de Abril de 2020, 22:49
Eu nao estou dentro do problema inicial (como deu para reparar ai em cima), mas em relacao a esses "esquemas da linguagem", eu faria de um modo que fosse explicito perceber o que se passa e o que se quer fazer.
Deve haver uma maneira de resolver esse problema que nao seja necessario conhecer o funcionamento binario das variaveis com sinal ou especificacoes da arquitectura.
Normalmente isso passa por usar os valores binario sem significado de sinal(usar sempre a informacao unsigned int ou fazer a conversao no inicio) e depois so no final fazer a conversao explicitamente (uma conta..).
Se nao, acontecem estas questoes "o que e' que ele esta a fazer por detras"?


Por exemplo, o seguinte codigo:

Código: [Seleccione]
#include <stdio.h>
#include <cstdint>

int main()
{
    uint8_t READXYZ[2];
    uint32_t u32value;
    int32_t s32value;
   
    READXYZ[0] = 0x61;
    READXYZ[1] = 0xff;
    u32value = ( READXYZ[0] | ( READXYZ[1] << 8 ) );
    s32value = -(0x10000 - u32value);
    printf("0x%08X    %d    0x%08X\n", u32value, s32value, s32value);
}

dá o seguinte resultado:

Código: [Seleccione]
0x0000FF61    -159    0xFFFFFF61

Neste caso quem desenvolve o codigo precisa de saber que o que vem no READXYZ e' um numero com sinal e a conversao se faz -(0x10000 - u32value);
Certo que é necessario saber alguma coisa.. e tambem pode nao ser o mais eficiente em termos de instrucoes.

Mas quem nao esta por dentro, pode nao entender porque e' que isto e' feito, mas pelo menos nao esta escondido pelo compilador, arquitectura ou magia obscura, as operacoes matematicas estao la e basta ler o codigo para conseguirmos chegar ao resultado final :)

Título: Re: STM32 inicio
Enviado por: Njay em 12 de Abril de 2020, 23:09
Por isso mesmo é que me limitei a dar informação genérica.
Título: Re: STM32 inicio
Enviado por: jm_araujo em 13 de Abril de 2020, 10:44
Lógica: o que o arduino está a fazer é "esticar" o sinal de um número de 16 bits (0xff61) para 32 bits.

Chama-se "estender o sinal". Alguns CPUs, se não todos, têm uma instrução para isso.

Quando copiamos de uma variável para outra maior com sinal, os bits mais significativos têm que ser iguais ao mais significativo da variável pequena, senão o sinal do número não é mantido. Por exemplo, passar -1 em 8 bits para -1 em 16 bits; se apenas copiarmos os 8 para os 8 menos significativos dos 16 com sinal, ficamos com 0x00ff, que não é -1 mas sim 255. O correcto é passar para 0xffff, que é -1 em 16 bits. A regra que faz a conversão correcta é pegar no bit mais significativo da variável pequena e replicá-lo pelos bits mais significativos da variável maior (estender o sinal):

-1 (8bits) = 1111 1111b -> 0000 0000 1111 1111b
mas o bit mais significativo é 1 e portanto repete-se nos restantes bits à esquerda
1111 1111 1111 1111b (16bits) = -1

Já se o valor original fosse 1 (ou qualquer valor positivo, que tem o bit mais significativo = 0), repetia-se 0 e o resultado final continua a ser 1
1 (8bits) = 0000 0001b -> 0000 0000 0000 0001b (16bits)

Em variáveis sem sinal, não se estende o sinal, os bits "novos", mais significativos do sinal, ficam sempre a zero.

Está tudo correto

Em C não tens de te preocupar com nada disso se definires as variáveis do tipo correto, as conversão são implícitas na linguagem.
Em C se fizeres
Código: [Seleccione]
    int8_t x;
    int16_t y;
    x=0xff;
    y=x;
    printf("%d  %d",x,y);
Tens como resultado "-1 -1", x e y ficam com o valor -1, não tens de extender o sinal explicitamente.

Com atribuições bitwise (&,|,<<,>>,~,^) é preciso mais algum cuidado, mas nada que uns testes não resolvam.
Eu nao estou dentro do problema inicial (como deu para reparar ai em cima), mas em relacao a esses "esquemas da linguagem", eu faria de um modo que fosse explicito perceber o que se passa e o que se quer fazer.
Deve haver uma maneira de resolver esse problema que nao seja necessario conhecer o funcionamento binario das variaveis com sinal ou especificacoes da arquitectura.
Normalmente isso passa por usar os valores binario sem significado de sinal(usar sempre a informacao unsigned int ou fazer a conversao no inicio) e depois so no final fazer a conversao explicitamente (uma conta..).
Se nao, acontecem estas questoes "o que e' que ele esta a fazer por detras"?


Por exemplo, o seguinte codigo:

Código: [Seleccione]
#include <stdio.h>
#include <cstdint>

int main()
{
    uint8_t READXYZ[2];
    uint32_t u32value;
    int32_t s32value;
   
    READXYZ[0] = 0x61;
    READXYZ[1] = 0xff;
    u32value = ( READXYZ[0] | ( READXYZ[1] << 8 ) );
    s32value = -(0x10000 - u32value);
    printf("0x%08X    %d    0x%08X\n", u32value, s32value, s32value);
}

dá o seguinte resultado:

Código: [Seleccione]
0x0000FF61    -159    0xFFFFFF61

Neste caso quem desenvolve o codigo precisa de saber que o que vem no READXYZ e' um numero com sinal e a conversao se faz -(0x10000 - u32value);
Certo que é necessario saber alguma coisa.. e tambem pode nao ser o mais eficiente em termos de instrucoes.

Mas quem nao esta por dentro, pode nao entender porque e' que isto e' feito, mas pelo menos nao esta escondido pelo compilador, arquitectura ou magia obscura, as operacoes matematicas estao la e basta ler o codigo para conseguirmos chegar ao resultado final :)



Esse código não é muito legível, nem amigável para micros: tens uma constante de 64 bits ("0x10000"), nem todos os compiladores vão comer sem calar, e vais ter uma penalização na execução pelas instruções extra (negação de uma subtração).
As explicações do código dão-se nos comentários, devemos deixar os compiladores fazer o seu trabalho. Se o C sabe converter entre tipos, devemos deixá-lo fazer.


Título: Re: STM32 inicio
Enviado por: KammutierSpule em 13 de Abril de 2020, 13:48
Esse código não é muito legível, nem amigável para micros: tens uma constante de 64 bits ("0x10000"), nem todos os compiladores vão comer sem calar, e vais ter uma penalização na execução pelas instruções extra (negação de uma subtração).

> Esse código não é muito legível

Pode nao ser compreensivel e nao se entender o proposito, mas legivel... é só a negacao da subtracao de um valor com uma variavel :)

> 64 bits, e vais ter uma penalização na execução pelas instruções extra (negação de uma subtração).

Sim, tinha dito que nao ia ser o mais eficiente.
Usei o u32/s32 para testes, ai nesse caso em concreto, servia usar so 16bits/32bits que ja ficava mais amigavel.


As explicações do código dão-se nos comentários, devemos deixar os compiladores fazer o seu trabalho. Se o C sabe converter entre tipos, devemos deixá-lo fazer.

Este caso e neste tipo de coisas que estamos a analisar entra muito na politica pessoal (ou o que estiver definido numa eventual politica de desenvolvimento de codigo interno numa empresa, por exemplo)
Eu pessoalmente, em relacao a isto de linguagens programacao, como tenho limitacoes cognitivas, nao consigo decorar todas as regras da linguagem.
Por exemplo, a questao do uso de ( ) para clarificar a precedencia de operacoes.. eu sei que existe uma tabela que define a ordem para todos os operadores da linguagem... mas nao vou estar a decora-la :) logo abuso do uso de ( ) mesmo nao sendo necessario a maior parte das vezes.
Título: Re: STM32 inicio
Enviado por: Njay em 13 de Abril de 2020, 15:21
Eu pessoalmente, em relacao a isto de linguagens programacao, como tenho limitacoes cognitivas, nao consigo decorar todas as regras da linguagem.
Por exemplo, a questao do uso de ( ) para clarificar a precedencia de operacoes.. eu sei que existe uma tabela que define a ordem para todos os operadores da linguagem... mas nao vou estar a decora-la :) logo abuso do uso de ( ) mesmo nao sendo necessario a maior parte das vezes.

Eu idem. Meto parenteses em tudo. É muito mais fácil e legível do que decorar as regras da precedência. E uso as partes mais básicas das linguagens. Não sou purista em linguagem nenhuma. Adoro C com classes. Tenho uma regra que é "quanto mais explicito, melhor" - quanto menos "background" de informação for necessário para entender um pedaço de código, melhor. Quanto mais linguagens se conhece maior o potencial de se ficar baralhado :D