主函数代码如下:
#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µÄÖµÊÇ42
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
NVIC_Configuration();// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é
uart_init(9600); //´®¿Ú³õʼ»¯Îª9600
LED_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; //Êä³öËÙ¶È50MHz
GPIO_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); //³õʼ»¯GPIOA
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //ÇÀÕ¼ÓÅÏȼ¶ 3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //×ÓÓÅÏȼ¶ 3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ ͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //ÖжÏÓÅÏȼ¶³õʼ»¯
//µÚ4²½£ºÅäÖÃUSART1²ÎÊý
USART_InitStructure.USART_BaudRate = bound; //²¨ÌØÂÊÉèÖãº57600
USART_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++;
// }else
Arduino_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=42
LED0=0;
// if( Arduino_Receive_Data[0]!=0x42)
// {
// Arduino_receive_counter++;
// }else
Arduino_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的中断函数学习基本的就可以自己进一步做了
本文介绍STM32F103RCT6单片机的串口通讯实践,包括串口中断服务函数的设计与应用、全局变量的声明与使用等关键技术点。通过实例讲解如何在两个单片机之间建立通讯,并分享了串口调试助手的使用技巧。
616

被折叠的 条评论
为什么被折叠?



