当前位置:网站首页>Compréhension approfondie de l'expérience de port série stm32 (registre) [Tutoriel de niveau nounou]

Compréhension approfondie de l'expérience de port série stm32 (registre) [Tutoriel de niveau nounou]

2022-06-26 11:09:00 La nuit est dure.

 Regardez d'abord cette image,,Comme vous pouvez le voir,USART_RX_STASimilaire à un16Registre des bits,Avant14Bit stocke les données,Les deux derniers détectent séparément0X0DEt0X0A.

Analyse suivante:

void uart_init(u32 pclk2,u32 bound)
{  	 
	float temp;
	u16 mantissa;                
	u16 fraction;	   
	temp=(float)(pclk2*1000000)/(bound*16);//Je l'ai.USARTDIV
	mantissa=temp;				 //Obtenez la partie entière
	fraction=(temp-mantissa)*16; //Pour obtenir la fraction décimale	 
    mantissa<<=4;
	mantissa+=fraction; 
	RCC->APB2ENR|=1<<2;   //ActiverPORTAHorloge de bouche  
	RCC->APB2ENR|=1<<14;  //Activer l'horloge série 
	GPIOA->CRH&=0XFFFFF00F;//IOParamètres d'état
	GPIOA->CRH|=0X000008B0;//IOParamètres d'état 
	RCC->APB2RSTR|=1<<14;   //Réinitialiser le port série1
	RCC->APB2RSTR&=~(1<<14);//Arrêtez de réinitialiser	   	   
	//Réglage du taux de Baud
 	USART1->BRR=mantissa; // Réglage du taux de Baud	 
	USART1->CR1|=0X200C;  //1Bit stop,Pas de bit de contrôle.
#if EN_USART1_RX		  //Si la réception est activée
	//Activer la réception des interruptions 
	USART1->CR1|=1<<5;    //Recevoir l'activation de la coupure non aérienne du tampon	    	
	MY_NVIC_Init(3,3,USART1_IRQn,2);//Groupe2,Priorité minimale 
#endif
}

temp=(float)(pclk2*1000000)/(bound*16); C'est une formule de calcul , Parce que le port série est activé 1,Et le port série1Oui.APB2ENRDans le registre( Les autres ports série sont dans le registre APB1ENRÀ l'intérieur),Parce queAPB2 Fréquence bit général 72M,EtAPB1 Fréquence bit général 36M.

 Donc icipclk2Pour72M,Etbound Est le taux de Baud que vous devez définir .

mantissa = temp Est simplement : Pour trouver la partie décimale

    fraction=(temp-mantissa)*16; //Pour obtenir la fraction décimale	 
    mantissa<<=4;

Ces deux lignes de code sont utilisées pour convertir les parties décimales et entières ,Convertir en16Décimal. Et l'enregistrer dans le registre de débit Baud . Suivi d'un port série activé 1EtPORTAHorloge( Port série 1 correspondant IOLa bouche estPA9,PA10, Il a besoin d'un capuchon de saut. ).

Et ensuite,IO Port zéro , Ensuite, définissez les entrées et les sorties séparément. ,

USART1->CR1|=0X200C;      Set to enable serial port 8Longueur des mots1Bits d'arrêt(USART_CR2Moyenne[13:12]Par défaut“0”)

MY_NVIC_Init(3,3,USART1_IRQn,2)

Les grouper en groupes 2À l'intérieur, Priorité de préemption pour le moment :La priorité de réponse est = 2:2,C'est - à - dire:(00-11)Quatre situations,Et3:3 Groupe sélectionné pour l'arrangement pour 2 Un cas où la priorité est la plus faible . Cela permet d'effectuer d'abord l'assignation du taux de Baud ci - dessus , Et l'activation du port série, etc. , Enfin, lancez cette ligne de code. .

Passons à la section suivante. :

u16 USART_RX_STA=0;       //Recevoir l'étiquette d'état	  
  
void USART1_IRQHandler(void)
{
	u8 res;	
#if SYSTEM_SUPPORT_OS 		//SiSYSTEM_SUPPORT_OSC'est vrai.,Besoin de soutienOS.
	OSIntEnter();    
#endif
	if(USART1->SR&(1<<5))	//Données reçues
	{	 
		res=USART1->DR; 
		if((USART_RX_STA&0x8000)==0)//Réception incomplète
		{
			if(USART_RX_STA&0x4000)//Reçu.0x0d
			{
				if(res!=0x0a)USART_RX_STA=0;//Erreur de réception,Recommencer
				else USART_RX_STA|=0x8000;	//Réception terminée 
			}
			else //Pas encore reçu0X0D
			{	
				if(res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0x3fff]=res;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//Erreur de réception des données,Redémarrer la réception	  
				}		 
			}
		}  		 									     
	}

Phase initiale: USART_RX_STA=0, Étiquette de l'état d'acceptation .

Passe d'abord par le registre d'état SRDeRXNEOui Non1,- Oui.1Les données ont été reçues,Sinon, non.. Immédiatement après cette définition, res Variable pour recevoir un octet du registre de données ,Et maintenantUSART_RX_STAPour0,Avec0X8000En cours&Opération,Les résultats sont les suivants:0, Non accepté , Continuez à juger. ,0X4000Effectuer et calculer,Pour voir si c'est0, C'est aussi un jugement sur l'acceptation de la route. 0X0D,Si ce n'est pas accepté,Prenez ça.res Variable stockée dans le tableau ,En ce momentUSART_RX_STAPour 0 Avec0X3fffEn cours&Opération, Et vous verrez , A cause de son front 14Les bits sont des bits de données, Donc vous verrez que la première variable est stockée dans BUF[0]À l'intérieur,La logique est probablement la suivante:

Donc chaque octet est stocké dans un bit de tableau spécifique  .

if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//Erreur de réception des données,Redémarrer la réception

Quand le tableau est hors de portée , Et ça recommence. .

Et ça va continuer. , Lorsque le BIT de données est plein ,Et puis...res Ce qui est accepté à l'intérieur 0X0D, Juge d'abord comme ci - dessus. USART_RX_STA Accepté ou non 0X0AEt0X0D.

Et ensuite:

if(res==0x0d)USART_RX_STA|=0x4000;

Oui.USART_RX_STA La quinzième position de 1,,Passons au prochain cycle,Cette foisres La valeur acceptée est 0X0A,

Et le jugement va

       if(USART_RX_STA&0x4000)//Reçu.0x0d
			{
				if(res!=0x0a)USART_RX_STA=0;//Erreur de réception,Recommencer
				else USART_RX_STA|=0x8000;	//Réception terminée 
			}

Donc l'exécutionUSART_RX_STA|=0x8000,De faireUSART_RX_STA Le seizième chiffre de 1.

Ensuite, regardez la section fonctions principales :

int main(void)
{			
	u8 t;
	u8 len;	
	u16 times=0;  
	Stm32_Clock_Init(9); //Réglage de l'horloge du système
	delay_init(72);	     //Initialisation retardée 
	uart_init(72,9600);	 //Le port série est initialisé comme9600 
	LED_Init();		  	 //Initialisation etLEDInterface matérielle connectée    
	while(1)
	{
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//Obtenir la longueur des données reçues cette fois
			printf("\r\nLe message que vous avez envoyé est:\r\n");
			for(t=0;t<len;t++)
			{
				USART1->DR=USART_RX_BUF[t];
				while((USART1->SR&0X40)==0);//Attendez la fin de l'envoi
			}
			printf("\r\n\r\n");//Insérer une nouvelle ligne
			USART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\nALIENTEK MiniSTM32Conseil de développement Expérience de port série\r\n");
				printf("Atome de point [email protected]\r\n\r\n\r\n");
			}
			if(times%200==0)printf("Veuillez saisir les données,Fin avec entrée\r\n");  
			if(times%30==0)LED0=!LED0;//ClignotantLED,Invite le système à fonctionner.
			delay_ms(10);   
		}
	}	 
}

if(USART_RX_STA&0x8000)                  Déterminer si elle a été reçue 0X0A

len=USART_RX_STA&0x3fff; Prenons un exemple simple. USART_RX_STAPour1100000000000011Et0X3fffEn cours&Opération,Le résultat est3, Représente naturellement la taille actuelle du tableau .

Phase finale, Mettre l'accent sur la compréhension des deux lignes de code suivantes :

USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//Attendez la fin de l'envoi

L'analyse est la suivante:: Enregistrer les informations de chaque groupe dans un registre de données , Le Registre des données donne les données à TDR,Quand le message est envoyé, Envoyé un par un , Chaque cadre de données a un bit de départ ,Bits de données, Et les bits d'arrêt , Lorsque les détails du registre de données sont détectés, l'envoi est terminé. ( C'est tout. TDR), Pour le moment TXE C'est devenu 1,Lorsqu'il est détectéTXEPour1Après,TCÇa va aussi devenir1(Le système fonctionne automatiquement). C'est pourquoi la deuxième ligne détecte la deuxième ligne du registre d'état 6Bit est1 Pour déterminer si cet octet a été envoyé avec succès .

De là.,Jugement directTXE Vous pouvez également déterminer si l'envoi est terminé

Le Code peut donc être modifié comme suit: :

        for(t=0;t<len;t++)
			{
				USART1->DR=USART_RX_BUF[t];
				while((USART1->SR&0X80)==0);//Attendez la fin de l'envoi
			}

原网站

版权声明
本文为[La nuit est dure.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206261013252144.html