Bonsoir je repars ds les conditions ternaires je me suis rendu fou avec la configuration des fonctions alternées, je pense retomber sur le résultat qu'il faut avoir dans le registre GPIOx_AFR:
Bits 31:0 AFRLy: Alternate function selection for port x bit y (y = 0..7)
These bits are written by software to configure alternate function I/Os
AFRLy selection:
0000: AF0
0001: AF1
0010: AF2
0011: AF3
0100: AF4
0101: AF5
0110: AF6
0111: AF7
1000: AF8
1001: AF9
1010: AF10
1011: AF11
1100: AF12
1101: AF13
1110: AF14
1111: AF15
Pour ma part je recherche a avoir la fonction alternée n°7 qui correspond a l'USART1 donc mon registre doit etre égal ==> 0b 0000 0111
Voici un morceau de la fonction qui permet d'associer la pin TX a la fonction USART:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| /**
* @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
* @param GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
* x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
* @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
* the configuration information for the specified GPIO peripheral.
* @retval None
*/
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t position;
uint32_t ioposition = 0x00;
uint32_t iocurrent = 0x00;
uint32_t temp = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
/* Configure the port pins */
for(position = 0; position < GPIO_NUMBER; position++)
{
/* Get the IO position */
ioposition = ((uint32_t)0x01) << position;
/* Get the current IO position */
iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
if(iocurrent == ioposition)
{
/*--------------------- GPIO Mode Configuration ------------------------*/
/* In case of Alternate function mode selection */
if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
{
/* Check the Alternate function parameter */
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
/* Configure Alternate function mapped with the current IO */
temp = GPIOx->AFR[position >> 3];
temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
GPIOx->AFR[position >> 3] = temp;
} |
Ensuite je vais lister les éléments manquant pour réussir a calculer ces conditions:
GPIO_NUMBER = 16 (pour la boucle for)
GPIO_Init->Pin = ((uint16_t)0x0200) (Pin 9 selected)
GPIO_Init->Alternate = ((uint8_t)0x07) (USART1 Alternate Function mapping)
Allez au boulot!
On passe les déclarations et assert_param qui sert juste a contrôler les paramètres rentrant, renvoi un 0 si ça correspond et un 1 si cela ne correspond pas, le 1 ayant pour conséquence de stopper le prg
Attaquons nous a la boucle for, donc tant que "position" n'est pas supérieur a 16, "position" s'incrémente.
Donc "position" vaut 1 puis 2 puis 3 etc...
Donc la variable "ioposition" va également changer en fonction de "position" et cela va nous intéresser au moment ou "position" = 9 car a ce moment "ioposition" = 0b 0000 0010 0000 0000 ou 0x 0200 (retenez cette valeur)
Passons a la ligne suivante, "iocurrent" prend la valeur d'un ET entre GPIO_Init->Pin & ioposition ==> 0b 0000 0010 0000 0000 & 0000 0010 0000 0000 ==> donc au moment ou position vaut 9 "iocurrent" = 0b 0000 0010 0000 0000.
On continu, toujours au moment ou "position" = 9 on entre dans la condition ==> if(iocurrent == ioposition)
Ensuite on entre également ds la condition ==> if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) car dans le fichier d'initialisation via la structure GPIO_InitTypeDef on a configuré le mode ==> GPIO_MODE_AF_PP ( avec AF = alternant function et PP = Push-Pull).
Rentrons ds le vif du sujet (assert_param déjà expliqué passons a la suite):
temp = GPIOx->AFR[position >> 3];
a l'issue de cette opération temp = 0b 0000 0001; (car 0000 1001 >> 3 = 0000 0001)
temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
a l'issue de cette opération temp = 0b 0000 0001.
Si je détail:
(position & (uint32_t)0x07)
0000 1001 & 0000 0111 = 0b 0000 0001
((uint32_t)(position & (uint32_t)0x07) * 4))
0000 0001 * 0000 0100 = 0b 0000 0100
((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4))
décalage de 0b 0000 1111 << 0b 0000 0100 = 0b 1111 0000
0b 0000 1111
0b 0000 0001 & 0b 0000 1111 = 0b 0000 0001 ==> nouvelle valeur de temp
Voila pour cette ligne, et première question pourquoi avoir fait cette ligne alors que temp vaut tjrs la mm valeur avt et après manipulation ?
Passons a la seconde lignes avec un début de calcul idem:
((uint32_t) position & (uint32_t)0x07)
0000 1001 & 0000 0111 = 0b 0000 0001
Sur cette ligne j'ai pu observé une différence d'associativité avec la ligne précédente les parenthèse ne sont pas placées au même endroit je ne pense pas qu'il y ait d'importance ds ce cas.
(((uint32_t) position & (uint32_t)0x07) * 4))
0000 0001 * 0000 0100 = 0b 0000 0100
((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4))
decalage de 0b 0000 0111 << 0b 0000 0100 = 0b 0011 1000
0b 0000 0001 | 0b 0011 1000 = 0b 0011 1001
Dernière ligne:
Pour cette ligne je n'en suis pas sur mais je pense que cela se produit comme ça car on retombe sur la valeur souhaitée car si on décale temp de 3 on obtient
GPIOx->AFR[position >> 3] = temp;
0b 0011 1001 >> 3 = 0b 0000 0111 t c'est la valeur qu'il faut pour que AF = 7 (voir le début du post).
Bon ben me suis bien cassé la tète et pour ce qui auront la foi de lire jusqu'au bout ce post merci pour votre aide!
Partager