欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

STM32串口学习总结(经典)

发布时间:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的这篇文章主要介绍了 STM32串口学习总结(经典) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

主函数代码如下:

#include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "arduino.h" //ALIENTEK Mini STM32¿ª·¢°å·¶Àý´úÂë3 //´®¿ÚʵÑé //¼¼ÊõÖ§³Ö£ºwww.openedv.com //¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾int main(void){ u8 t;u8 len; u16 times=0; u8 ax;//u8 bx='*'; //*µÄʵ¼ÊÖµÆäʵ´ú±í0x42Ò²¾ÍÊÇASCIIµÄÖµÊÇ42delay_init(); //ÑÓʱº¯Êý³õʼ»¯ NVIC_Configuration();// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×éuart_init(9600); //´®¿Ú³õʼ»¯Îª9600LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú USART3_Config(115200);while(1){delay_ms(100);LED0=1;LED1=1;//GPIO_ResetBits(GPIOA,GPIO_Pin_8);ax=arduino_Analysis();//printf("sudo=%d \r\n",sudu);//printf("ax=%d \r\n",ax);//printf("cx=%d \r\n",cx);//printf("%d \r\n",bx);//delay_ms(1000);//////////////////////////////////Ô­º¯Êý // LED0=!LED0; // if(USART_RX_STA&0x8000) // { // len=USART_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È // printf("\r\nÄú·¢Ë͵ÄÏûϢΪ:\r\n"); // for(t=0;t<len;t++) // { // USART1->DR=USART_RX_BUF[t]; // while((USART1->SR&0X40)==0);//µÈ´ý·¢ËͽáÊø // } // printf("\r\n\r\n");//²åÈë»»ÐÐ // USART_RX_STA=0; // }else // { // times++; // if(times%5000==0) // { // printf("\r\nALIENTEK MiniSTM32¿ª·¢°å ´®¿ÚʵÑé\r\n"); // printf("ÕýµãÔ­×Ó@ALIENTEK\r\n\r\n\r\n"); // } // if(times%200==0)printf("ÇëÊäÈëÊý¾Ý,ÒԻسµ¼ü½áÊø\r\n"); // //ÉÁ˸LED,ÌáʾϵͳÕýÔÚÔËÐÐ. // delay_ms(10); // //} // } } }

需要串口服务工程
建立与Arduino板子的通讯
.c程序如下:

#include "arduino.h"u8 Res=0; int i; u8 Arduino_sudo; u8 Arduino_jiaodu; u8 sudu; u8 jiaodu; u8 x=7; char cx; u8 USART3_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú. //½ÓÊÕ״̬ u8 Arduino_Receive_Data[10]; u8 Arduino_receive_counter=0; u8 Arduino_receive_flag=0; //u8 Arduino_receive_temp[10]={0x42,0x39,0x49,0x39,0x45,0x39,0x49,0x54,0x39,0X39}; u8 Arduino_receive_temp[10]; //u8 res[8]; //bit15£¬ ½ÓÊÕÍê³É±êÖ¾ //bit14£¬ ½ÓÊÕµ½0x0d //bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿ u16 USART3_RX_STA=0; //½ÓÊÕ״̬±ê¼Ç void USART3_Config(u32 bound) //Á¬½ÓÊý´«µç̨ ³õʼ»¯ ÅäÖÃUSART2 {GPIO_InitTypeDef GPIO_InitStructure; //´®¿Ú¶Ë¿ÚÅäÖýṹÌå±äÁ¿USART_InitTypeDef USART_InitStructure; //´®¿Ú²ÎÊýÅäÖýṹÌå±äÁ¿NVIC_InitTypeDef NVIC_InitStructure;//µÚ1²½£º´ò¿ªGPIOºÍUSART²¿¼þµÄʱÖÓRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //´ò¿ªGPIOAʱÖÓºÍGPIOA¸´ÓÃʱÖÓRCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //´ò¿ª´®¿Ú¸´ÓÃʱÖÓUSART_DeInit(USART3); //¸´Î»´®¿Ú1//µÚ2²½£º½«USART2 Tx£¨·¢Ëͽţ©µÄGPIOÅäÖÃÎªÍÆÍ츴ÓÃģʽGPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //´®¿Ú2·¢ËͽÅ//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³öGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Êä³öËÙ¶È50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //³õʼ»¯GPIOA//µÚ3²½£º½«USART2 Rx£¨½ÓÊսţ©µÄGPIOÅäÖÃΪ¸¡¿ÕÊäÈëģʽGPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //´®¿Ú2½ÓÊÕ½ÅGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //¸¡¿ÕÊäÈë//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //ÉÏÀ­ÊäÈëGPIO_Init(GPIOB, &GPIO_InitStructure); //³õʼ»¯GPIOANVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //ÇÀÕ¼ÓÅÏȼ¶ 3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //×ÓÓÅÏȼ¶ 3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ ͨµÀʹÄÜNVIC_Init(&NVIC_InitStructure); //ÖжÏÓÅÏȼ¶³õʼ»¯//µÚ4²½£ºÅäÖÃUSART1²ÎÊýUSART_InitStructure.USART_BaudRate = bound; //²¨ÌØÂÊÉèÖãº57600USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Êý¾ÝλÊýÉèÖãº8λUSART_InitStructure.USART_StopBits = USART_StopBits_1; //ֹͣλÉèÖãº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; //½ÓÊÕÓë·¢ËͶ¼Ê¹ÄÜUSART_Init(USART3, &USART_InitStructure); //³õʼ»¯USART2//´ò¿ª·¢ËÍÖжϺͽÓÊÕÖжÏ(Èç¹ûÐèÒªÖжÏ)// USART_ITConfig(USART2, USART_IT_TXE, ENABLE); // ʹÄÜÖ¸¶¨µÄUSART1·¢ËÍÖÐ¶Ï £»USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // ʹÄÜÖ¸¶¨µÄUSART1½ÓÊÕÖÐ¶Ï £»//µÚ5²½£ºÊ¹ÄÜ USART2£¬ ÅäÖÃÍê±ÏUSART_Cmd(USART3, ENABLE); //ʹÄÜ USART2//ÈçÏÂÓï¾ä½â¾öµÚ1¸ö×Ö½ÚÎÞ·¨ÕýÈ··¢ËͳöÈ¥µÄÎÊÌâUSART_ClearFlag(USART3, USART_FLAG_TC); //Çå´®¿Ú2·¢ËͱêÖ¾}void USART3_IRQHandler(void) //´®¿Ú3ÖжϷþÎñ³ÌÐò{if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏÓÐЧ,Èô½ÓÊÕÊý¾Ý¼Ä´æÆ÷Âú{Arduino_receive_temp[Arduino_receive_counter]=USART_ReceiveData(USART3);// Res=USART_ReceiveData(USART3);// printf("res=%d",Res);// USART_SendData(USART3,Res);// LED1=!LED1;if((Arduino_receive_counter==0)&&(Arduino_receive_temp[0]!=42)) return;/////87=W Ê×Ö¡LED0=0; // if( Arduino_Receive_Data[0]!=0x42) // { // Arduino_receive_counter++; // }elseArduino_receive_counter++;if(Arduino_receive_counter==9){Arduino_receive_counter=0;Arduino_receive_flag=1;}}}u8 arduino_Analysis() {if(Arduino_receive_flag==1){Arduino_receive_flag=0;memcpy(Arduino_Receive_Data,Arduino_receive_temp,8);//memcpy(Arduino_receive_temp,Arduino_Receive_Data,8);LED1=0; // for(i=0;i<8;i++) // { // // printf("Arduino_Receive_Data[%d]=%d\r\n",i,Arduino_Receive_Data[i]); // } }printf("sudu=%d \r\n",Arduino_Receive_Data[2]-48);jiaodu=(Arduino_Receive_Data[6]-48)*10+(Arduino_Receive_Data[7]-48);if(Arduino_Receive_Data[4]==45){printf("jiaodu=-%d \r\n",jiaodu);}else{printf("jiaodu=%d \r\n",jiaodu);}//cx=Arduino_receive_temp[2];//Res =Arduino_Receive_Data[Arduino_receive_counter]; //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý//return Arduino_receive_temp[2];//sudu=Arduino_receive_temp[7];}/////////////////////////////////////////////////////////////// Arduino.h的程序如下: #ifndef _ARDUINO_H #define _ARDUINO_H #include "stdio.h" #include "usart.h" #include "stm32f10x.h" #include "stm32f10x_conf.h" #include "string.h" #include "led.h" #include "sys.h" #include "delay.h"void USART3_Config(u32 bound); // //void USART3_IRQHandler(void); //void TIM4_Init(u16 arr,u16 psc); //void TIM4_IRQHandler(void); void TIM4_Init(u16 arr,u16 psc); u8 arduino_Analysis(void);#define USART3_REC_LEN 200 //¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200 #define EN_USART3_RX 1 //ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ extern u8 sudu; extern char cx; //Èç¹ûÏë´®¿ÚÖжϽÓÊÕ£¬Ç벻ҪעÊÍÒÔϺ궨Òå#endif

总结以及函数的说明,今天系统的学习了单片机的串口通讯,简单的建立基于两个单片机的通讯使用单片机型号是stm32f103 rct6
1.在MDK中建立工程的过程中,在函数dianC中定义的相关函数,都在点h中进行相应的声明,但是除了void USART3_IRQHandler(void)以及void TIM4_Init(u16 arr,u16 psc)和void TIM4_IRQHandler(void) void TIM4_Init(u16 arr,u16 psc)。像串口中断服务函数这样的函数,在进行编程的时候它是在库函数中已经定义好的函数,只要串口发生中中断,就会进入串口中断函数,执行相应的操作。除此之外所有的自己定义的函数都要在.h中进行相应的声明。
2.要想在.h中进行引用自己编写工程中的全局变量,例如使用Arduino.c中的变量sudo,要在Aduino.h中像如下:extern u8 sudu;外部一下才能够使用
3.如果想在main.c中使用某个.c文件中相应的函数处理的某个数据,当遇到需要一个以上的数据的时候,使用return语句就显得不合时宜,return处理这样的数据也有点吃力,这时候可以考虑使用全局变量并在Arduino.h中进行extern一下就行了,使用的实例如下所示:

u8 Res=0; int i; u8 Arduino_sudo; u8 Arduino_jiaodu; u8 sudu; u8 jiaodu; u8 x=7; char cx; u8 arduino_Analysis() {if(Arduino_receive_flag==1){Arduino_receive_flag=0;memcpy(Arduino_Receive_Data,Arduino_receive_temp,8);//memcpy(Arduino_receive_temp,Arduino_Receive_Data,8);LED1=0;printf("sudu=%d \r\n",Arduino_Receive_Data[2]-48);jiaodu=(Arduino_Receive_Data[6]-48)*10+(Arduino_Receive_Data[7]-48);if(Arduino_Receive_Data[4]==45){printf("jiaodu=-%d \r\n",jiaodu);}else{printf("jiaodu=%d \r\n",jiaodu);}sudu=Arduino_receive_temp[7];} }

像sudu=Arduino_receive_temp[7];这时候在主函数想要引用只需要在Arduino.h中extern一下sudu就行了。全局变量可以直接相当于函数的返回在主函数中使用

4.串口中断函数void USART3_IRQHandler(void)只要串口3进入中断,就会跳到串口中断函数void USART3_IRQHandler(void)处理串口中断函数中的相应的命令。

5.关于串口调试助手相关的说明,在进行这个实验的时候,由于串口3使用的bound是115200,但是串口1使用的bound是9600。当你使用串口打印函数:printf的时候,其实库函数中是默认使用串口1进行打印的,因此配置串口的使用9600,而不是115200.因为虽然你使用的是串口3进行通讯,但是单片机与电脑的串口助手进行通讯使用的是串口1,因此无论在任何地方使用串口的打印函数都要使用串口1的配置环境。

6.ASCII问题说明:在进形多机通讯的时候,以Arduino板子为例。当Arduino板子发来数字1的时候,32的板子接收过来就是一个数字1,但是当Arduino的板子发来的是一串字符串的时候比如:‘,6,-,11,’,这个时候其实32的板子接收的是一串数字(补充:串口中所定义的8bit(11111111)0-255,字节(byte)这是计算机中数据类型最基本的单位了,8bit 组成1byte,因此串口在进行数据的传输的过程中是每次传输八个比特,一个字节也就是数据被拆分成一个一个字符的 进行数据传送因此,数据,6,-,11,被拆分为(42 44 54 44 45 44 49 49)ASCII的形式)
如下形式

if((Arduino_receive_counter==0)&&(Arduino_receive_temp[0]!=42)) return;

if((Arduino_receive_counter==0)&&(Arduino_receive_temp[0]!=0x2a)) return;

所实现的功能是一样的,进行通讯的时候,其它的单片机传过来的数据都是一个一个的数字(0-255)形式进行解析的,因此开头的“”*“”的ASCII码就是42=0x2a写成十六进制的还是十进制的都行,进行编译之后单片机所接受的二进制的数是一样的。

6.函数怎样处理的说明,尽量不要在中断服务函数中进行数据的处理,加上一个标志位再在中断函数的外部进行函数的处理如下:

void USART3_IRQHandler(void) //´®¿Ú3ÖжϷþÎñ³ÌÐò{if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏÓÐЧ,Èô½ÓÊÕÊý¾Ý¼Ä´æÆ÷Âú{Arduino_receive_temp[Arduino_receive_counter]=USART_ReceiveData(USART3);// Res=USART_ReceiveData(USART3);// printf("res=%d",Res);// USART_SendData(USART3,Res);// LED1=!LED1;if((Arduino_receive_counter==0)&&(Arduino_receive_temp[0]!=42)) return;/87=W Ê×Ö¡//if((Arduino_receive_counter==0)&&(Arduino_receive_temp[0]!=0x2a)) return; //˵Ã÷£¬0x2a=42LED0=0; // if( Arduino_Receive_Data[0]!=0x42) // { // Arduino_receive_counter++; // }elseArduino_receive_counter++;if(Arduino_receive_counter==9){Arduino_receive_counter=0;Arduino_receive_flag=1;}}}u8 arduino_Analysis() {if(Arduino_receive_flag==1){Arduino_receive_flag=0;memcpy(Arduino_Receive_Data,Arduino_receive_temp,8);//memcpy(Arduino_receive_temp,Arduino_Receive_Data,8);LED1=0;printf("sudu=%d \r\n",Arduino_Receive_Data[2]-48);jiaodu=(Arduino_Receive_Data[6]-48)*10+(Arduino_Receive_Data[7]-48);if(Arduino_Receive_Data[4]==45){printf("jiaodu=-%d \r\n",jiaodu);}else{printf("jiaodu=%d \r\n",jiaodu);}sudu=Arduino_receive_temp[7];} }

就像上面的函数一样定义一个全局的变量u8 Arduino_receive_flag=0;,当进入到中断函数的时候就会是标志位置1,当标志位置1的时候函数u8 arduino_Analysis()中的if语句就开始执行`if(Arduino_receive_flag==1)
{

Arduino_receive_flag=0;memcpy(Arduino_Receive_Data,Arduino_receive_temp,8);//memcpy(Arduino_receive_temp,Arduino_Receive_Data,8);LED1=0; printf("sudu=%d \r\n",Arduino_Receive_Data[2]-48);

jiaodu=(Arduino_Receive_Data[6]-48)*10+(Arduino_Receive_Data[7]-48);
if(Arduino_Receive_Data[4]==45)
{
printf(“jiaodu=-%d \r\n”,jiaodu);
}else
{
printf(“jiaodu=%d \r\n”,jiaodu);
}

sudu=Arduino_receive_temp[7];

}`
到此处一个STM32的中断函数学习基本的就可以自己进一步做了

与50位技术专家面对面20年技术见证,附赠技术全景图

总结

以上是生活随笔为你收集整理的STM32串口学习总结(经典)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。