cubemx配置工程 ,usmart移植

发布时间 2023-05-26 20:57:13作者: 了不起的亮亮

一、usmart介绍

1、usmart简介

本USMART调试组件是正点原子开发提供的,主要功能是通过串口调试单片机里的函数,并执行。对于代码调试很有帮助。

我们普通的代码调试是通过:改写函数,修改参数,编译下载,查看结果;如果不满意的话继续这个流程。这样流程很麻烦而且单片机也是有寿命的,如此往复有损寿命。

使用USMART调试组件,只需要在串口调试助手里面输入函数以及参数,然后通过串口直接发送给单片机,就执行了一次参数调整,不满意的话可以在串口调试助手里面修改参数然后继续向单片机发送就可以了,直到满意为止。

例如我们调试lcd屏幕上显示的内容、位置、以及显示数字大小时,USMART组件的使用就可以让我们通过串口调试助手向单片机不断发送lcd屏幕的显示指令,我们可以不断调整文字的位置大小等等,直到符合预期,最后在代码中添加符合预期的代码参数就好了。而不用在代码中一次次的修改参数,编译,最后下载到单片机中查看结果。

2、usmart组件包含的文件以及介绍

usmart组件总共包含六个文件:如下图所示

(1)readme.txt是说明文件。

(2)usmart.c负责与外部交互;

  usmart.h是头文件,其中有用户配置的宏定义,可以用来配置usmart的功能以及总参数          的长度(直接和SRAM占用挂钩)、是否使能定时器扫描、是否使用读写函数等。

(3)usmart_str.c负责命令和参数解析;usamrt_str.h是其头文件。

(4)usmart_config.c文件是用户用来添加一些需要用usmart管理的函数。

3、usamrt实现的流程

usmart组件的使用包含以下几个步骤:

(1)在usmart_config.c中添加我们需要调用的函数(在usmart_nametab数组中添加),只有添加了函数我们才能用usmart组件在串口调试助手中输入,调用这个函数的功能。

(2)初始化串口,串口初始完成才能通过对应串口向单片机发送调试函数命令。

(3)初始化usmart,通过usmart_init函数实现

(4)轮询usmart_scan函数,处理串口数据。

 

二、cubemx工程配置

 cubemx工程配置,根据正点原子提供的usmart调试组件,对于usmart移植来讲,需要使用到串口1和定时器4,因此在cubemx中需要对串口1和定时器4进行初始化。

串口1是串口调试助手和单片机交互用的,需要配置串口的波特率,使能串口1中断等。如下图所示:

定时器4是用来实现定时扫描功能的,使能了定时器中断,并在中断中调用usmart_scan函数,以实现串口数据处理。

其中定时器4的初始化和中断服务函数放在了usmart.c,为了方便移植,我们直接用usmart.c中定义的定时器相关函数。因此,在这里我们需要随意定义和初始化一个定时器(在这里为定时器1),保证生成的“uvprojx”工程加载文件 "stm32f4xx_hal_tim.h",这样就可以保证在usmart.c文件中定义的“”TIM_HandleTypeDef”结构体时候不会报错,也即我们可以用库函数自己定义定时器4的的相关内容。

 

 

三、usmart相关文件的移植

cubemx初始化完成串口1和定时器1之后,我们就可以开始移植usmart文件了:

usmart文件夹直接复制黏贴到项目文件夹内,

然后在keil工程中,添加usmart文件夹中c文件,并在target中添加头文件路径。

 

由以上介绍可知,usmart中有六个文件,其中readme.txt为说明文件,剩余五个文件中,需要我们更改的是usmart.c、usmart.h、usmart_config.c。

(一)usmart.c文件修改

                      

 正点原子usmart.c文件包含三个头文件,其中usart.h为串口1头文件,sys.h为时钟初始化头文件,也包含了一些常用的数据类型短关键字(例如u32、u16、u8等)。

串口1和时钟初始化我们已经在cubemx中定义完成。其中生成的时钟初始化的代码放在了main.c中的SystemClock_Config()函数:

 sys.h包含的一些常用的数据类型短关键字(例如u32、u16、u8等),我们可以将其放在其他的头文件中,例如延时函数头文件delay.h中,注意的是,如果需要使用这些数据类型短关键字,也需要包含delay.h。

所以,我们将数据类型短关键字的定义放到delay.h中,然后在usmart.c中就可以直接删除#include”sys.h“。

此外由于usmart.c中把定时器4的相关内容也包括进来了,需要添加:

#include "stm32f4xx_hal_tim.h"

才能使得定时器4的相关定义内容不报错。

此外在usmart.c文件中对定时器4的初始化需要根据情况修改:如中断优先级等,在这里我随便设置的,自己可以根据设置的优先级分组适当调整。

HAL_NVIC_SetPriority(TIM4_IRQn,0,0);    //设置中断优先级,抢占优先级0,子优先级0

还有对于定时器中断的时间,定时器4的时钟频率来源于APB1,这里的sysclk为APB1的时钟频率,根据自己cubemx配置的时钟频率,来填写usmart_dev.init(sysclk)中的sysclk。

1 //sysclk:系统时钟(Mhz)
2 void usmart_init(u8 sysclk)
3 {
4 #if USMART_ENTIMX_SCAN==1
5     Timer4_Init(64535,(u32)sysclk*100-1);//分频,时钟为10K ,100ms中断一次,注意,计数频率必须为10Khz,以和runtime单位(0.1ms)同步.
6 #endif
7     usmart_dev.sptype=1;    //十六进制显示参数
8 }

由于定时器是向上计数,最大值为65535,分频因子为sysclk*100-1,即为10khz,所需要达到100ms中断一次,需要计数1000次,65535-1000=64535为定时器自动重装值。

(二)cubemx生成的usart.c文件修改

cubemx生成的串口1初始化文件为usart.c,头文件为usart.h,在usmart.c中可以直接包含这个头文件。但是需要做出一些修改。

修改内容包括:添加支持printf()函数的代码、重写中断服务函数 USART1_IRQHandler(void) 、添加串口1中断回调函数  HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)。

1、首先为了支持printf()函数,需要在usart.c中添加如下代码:

#pragma import(__use_no_semihosting)             
            
struct __FILE 
{ 
    int handle; 
 
}; 
 
FILE __stdout;       
  
void _sys_exit(int x) 
{ 
    x = x; 
} 

int fputc(int ch, FILE *f)
{      
   
    HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
    return ch;
    
//    while((USART1->SR&0X40)==0);//
//    USART1->DR = (uint8_t) ch;      
//    return ch;
}
支持printf的相关代码

2、重写中断服务函数USART1_IRQHandler(void)

我们使用正点原子提供的中断服务函数来接收数据,需要将cubemx生成的usart.c做一定的修改。

(1)首先usart.c中添加变量:

1 u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
2 u16 USART_RX_STA=0;       //接收状态标记:bit15,接收完成标志;bit14:;接收到0x0d;bit13~0,接收到的有效字节数目
3 u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲

usart.h中添加定义:

1 #define USART_REC_LEN              200      //定义最大接收字节数 200
2 #define RXBUFFERSIZE   1 //缓存大小
3 
4 extern u16 USART_RX_STA;                 //接收状态标记    
5 extern u8 aRxBuffer[RXBUFFERSIZE];//HAL库USART接收Buffer
6 extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 

cubemx生成的usart.c文件中已经定义了串口1的句柄为huart1:

1 UART_HandleTypeDef huart1;

而正点原子定义的句柄为UART1_Handler:

UART_HandleTypeDef UART1_Handler; //UART句柄

因此在cubemx生成的usart.c文件中,需要把UART1_Handler的定义删除,并把使用到UART1_Handler的地方替换为huart1

(2)其次添加中断服务函数

 1 //串口1中断服务程序(其中使用到串口句柄的地方,已经更改为huart1)
 2 void USART1_IRQHandler(void)                    
 3 { 
 4     u32 timeout=0;
 5     HAL_UART_IRQHandler(&huart1);    //调用HAL库中断处理公用函数
 6     
 7     timeout=0;
 8     while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)//等待就绪
 9     {
10      timeout++;////超时处理
11      if(timeout>HAL_MAX_DELAY) break;        
12     
13     }
14      
15     timeout=0;
16     while(HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
17     {
18      timeout++; //超时处理
19      if(timeout>HAL_MAX_DELAY) break;    
20     }
21 } 

特别注意的是:cubemx配置完串口1并使能中断之后,也会生成中断服务函数,在stm32f4xx_it.c文件中:

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

因为我们已经重写了中断服务函数,需要将这些代码全部注释掉。

(3)添加串口回调函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

 1 //串口1回调函数
 2 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
 3 {
 4     if(huart->Instance==USART1)//如果是串口1
 5     {
 6         if((USART_RX_STA&0x8000)==0)//接收未完成
 7         {
 8             if(USART_RX_STA&0x4000)//接收到了0x0d
 9             {
10                 if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
11                 else USART_RX_STA|=0x8000;    //接收完成了 
12             }
13             else //还没收到0X0D
14             {    
15                 if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
16                 else
17                 {
18                     USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
19                     USART_RX_STA++;
20                     if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收      
21                 }         
22             }
23         }
24 
25     }
26 }
View Code

(4)最后,需要开启串口1接收中断

在串口1的初始化完成之后开启接收中断 :HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE);

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
  /* USER CODE END USART1_Init 2 */

}

 

(三)usmart_config.c文件修改

 在usamrt_config.c文件中添加要调试的函数,首先要包含该函数的头文件,其次按照如下所给代码的格式来添加对应的函数就好了:

1     (void*)LCD_Display_Dir,"void LCD_Display_Dir(u8 dir)",
2     (void*)LCD_ShowxNum,"void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)", 

(四)main.c文件修改

在main.c中添加头文件usmart.h,然后添加usmart组件初始化函数:

1 usmart_dev.init(84);

四、所有配置完成之后的文件

usmart.c

  1 #include "usmart.h"
  2 #include "usart.h"
  3 #include "delay.h"
  4 #include "stm32f4xx_hal_tim.h"
  5 
  6 TIM_HandleTypeDef TIM4_Handler;      //定时器句柄 
  7 //系统命令
  8 u8 *sys_cmd_tab[]=
  9 {
 10     "?",
 11     "help",
 12     "list",
 13     "id",
 14     "hex",
 15     "dec",
 16     "runtime",       
 17 };        
 18 //处理系统指令
 19 //0,成功处理;其他,错误代码;
 20 u8 usmart_sys_cmd_exe(u8 *str)
 21 {
 22     u8 i;
 23     u8 sfname[MAX_FNAME_LEN];//存放本地函数名
 24     u8 pnum;
 25     u8 rval;
 26     u32 res;  
 27     res=usmart_get_cmdname(str,sfname,&i,MAX_FNAME_LEN);//得到指令及指令长度
 28     if(res)return USMART_FUNCERR;//错误的指令 
 29     str+=i;                          
 30     for(i=0;i<sizeof(sys_cmd_tab)/4;i++)//支持的系统指令
 31     {
 32         if(usmart_strcmp(sfname,sys_cmd_tab[i])==0)break;
 33     }
 34     switch(i)
 35     {                       
 36         case 0:
 37         case 1://帮助指令
 38             printf("\r\n");
 39 #if USMART_USE_HELP 
 40             printf("------------------------USMART V3.3------------------------ \r\n");
 41             printf("    USMART是由ALIENTEK开发的一个灵巧的串口调试互交组件,通过 \r\n");
 42             printf("它,你可以通过串口助手调用程序里面的任何函数,并执行.因此,你可\r\n");
 43             printf("以随意更改函数的输入参数(支持数字(10/16进制,支持负数)、字符串\r\n"),
 44             printf("、函数入口地址等作为参数),单个函数最多支持10个输入参数,并支持\r\n"),  
 45             printf("函数返回值显示.支持参数显示进制设置功能,支持进制转换功能.\r\n");
 46             printf("技术支持:www.openedv.com\r\n");
 47             printf("USMART有7个系统命令(必须小写):\r\n");
 48             printf("?:      获取帮助信息\r\n");
 49             printf("help:   获取帮助信息\r\n");
 50             printf("list:   可用的函数列表\r\n\n");
 51             printf("id:     可用函数的ID列表\r\n\n");
 52             printf("hex:    参数16进制显示,后跟空格+数字即执行进制转换\r\n\n");
 53             printf("dec:    参数10进制显示,后跟空格+数字即执行进制转换\r\n\n");
 54             printf("runtime:1,开启函数运行计时;0,关闭函数运行计时;\r\n\n");
 55             printf("请按照程序编写格式输入函数名及参数并以回车键结束.\r\n");    
 56             printf("--------------------------ALIENTEK------------------------- \r\n");
 57 #else
 58             printf("指令失效\r\n");
 59 #endif
 60             break;
 61         case 2://查询指令
 62             printf("\r\n");
 63             printf("-------------------------函数清单--------------------------- \r\n");
 64             for(i=0;i<usmart_dev.fnum;i++)printf("%s\r\n",usmart_dev.funs[i].name);
 65             printf("\r\n");
 66             break;     
 67         case 3://查询ID
 68             printf("\r\n");
 69             printf("-------------------------函数 ID --------------------------- \r\n");
 70             for(i=0;i<usmart_dev.fnum;i++)
 71             {
 72                 usmart_get_fname((u8*)usmart_dev.funs[i].name,sfname,&pnum,&rval);//得到本地函数名 
 73                 printf("%s id is:\r\n0X%08X\r\n",sfname,usmart_dev.funs[i].func); //显示ID
 74             }
 75             printf("\r\n");
 76             break;
 77         case 4://hex指令
 78             printf("\r\n");
 79             usmart_get_aparm(str,sfname,&i);
 80             if(i==0)//参数正常
 81             {
 82                 i=usmart_str2num(sfname,&res);           //记录该参数    
 83                 if(i==0)                              //进制转换功能
 84                 {
 85                     printf("HEX:0X%X\r\n",res);           //转为16进制
 86                 }else if(i!=4)return USMART_PARMERR;//参数错误.
 87                 else                                    //参数显示设定功能
 88                 {
 89                     printf("16进制参数显示!\r\n");
 90                     usmart_dev.sptype=SP_TYPE_HEX;  
 91                 }
 92 
 93             }else return USMART_PARMERR;            //参数错误.
 94             printf("\r\n"); 
 95             break;
 96         case 5://dec指令
 97             printf("\r\n");
 98             usmart_get_aparm(str,sfname,&i);
 99             if(i==0)//参数正常
100             {
101                 i=usmart_str2num(sfname,&res);           //记录该参数    
102                 if(i==0)                               //进制转换功能
103                 {
104                     printf("DEC:%lu\r\n",res);           //转为10进制
105                 }else if(i!=4)return USMART_PARMERR;//参数错误.
106                 else                                    //参数显示设定功能
107                 {
108                     printf("10进制参数显示!\r\n");
109                     usmart_dev.sptype=SP_TYPE_DEC;  
110                 }
111 
112             }else return USMART_PARMERR;            //参数错误. 
113             printf("\r\n"); 
114             break;     
115         case 6://runtime指令,设置是否显示函数执行时间
116             printf("\r\n");
117             usmart_get_aparm(str,sfname,&i);
118             if(i==0)//参数正常
119             {
120                 i=usmart_str2num(sfname,&res);               //记录该参数    
121                 if(i==0)                                   //读取指定地址数据功能
122                 {
123                     if(USMART_ENTIMX_SCAN==0)printf("\r\nError! \r\nTo EN RunTime function,Please set USMART_ENTIMX_SCAN = 1 first!\r\n");//报错
124                     else
125                     {
126                         usmart_dev.runtimeflag=res;
127                         if(usmart_dev.runtimeflag)printf("Run Time Calculation ON\r\n");
128                         else printf("Run Time Calculation OFF\r\n"); 
129                     }
130                 }else return USMART_PARMERR;               //未带参数,或者参数错误     
131              }else return USMART_PARMERR;                //参数错误. 
132             printf("\r\n"); 
133             break;        
134         default://非法指令
135             return USMART_FUNCERR;
136     }
137     return 0;
138 }
139 ////////////////////////////////////////////////////////////////////////////////////////
140 //移植注意:本例是以stm32为例,如果要移植到其他mcu,请做相应修改.
141 //usmart_reset_runtime,清除函数运行时间,连同定时器的计数寄存器以及标志位一起清零.并设置重装载值为最大,以最大限度的延长计时时间.
142 //usmart_get_runtime,获取函数运行时间,通过读取CNT值获取,由于usmart是通过中断调用的函数,所以定时器中断不再有效,此时最大限度
143 //只能统计2次CNT的值,也就是清零后+溢出一次,当溢出超过2次,没法处理,所以最大延时,控制在:2*计数器CNT*0.1ms.对STM32来说,是:13.1s左右
144 //其他的:TIM4_IRQHandler和Timer4_Init,需要根据MCU特点自行修改.确保计数器计数频率为:10Khz即可.另外,定时器不要开启自动重装载功能!!
145 
146 #if USMART_ENTIMX_SCAN==1
147 //复位runtime
148 //需要根据所移植到的MCU的定时器参数进行修改
149 void usmart_reset_runtime(void)
150 {
151     __HAL_TIM_CLEAR_FLAG(&TIM4_Handler,TIM_FLAG_UPDATE);//清除中断标志位 
152     __HAL_TIM_SET_AUTORELOAD(&TIM4_Handler,0XFFFF);     //将重装载值设置到最大
153     __HAL_TIM_SET_COUNTER(&TIM4_Handler,0);             //清空定时器的CNT
154     usmart_dev.runtime=0;    
155 }
156 //获得runtime时间
157 //返回值:执行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
158 //需要根据所移植到的MCU的定时器参数进行修改
159 u32 usmart_get_runtime(void)
160 {
161     if(__HAL_TIM_GET_FLAG(&TIM4_Handler,TIM_FLAG_UPDATE)==SET)//在运行期间,产生了定时器溢出
162     {
163         usmart_dev.runtime+=0XFFFF;
164     }
165     usmart_dev.runtime+=__HAL_TIM_GET_COUNTER(&TIM4_Handler);
166     return usmart_dev.runtime;        //返回计数值
167 }  
168 //下面这两个函数,非USMART函数,放到这里,仅仅方便移植. 
169 //定时器4中断服务程序     
170 void TIM4_IRQHandler(void)
171 {                                          
172     if(__HAL_TIM_GET_IT_SOURCE(&TIM4_Handler,TIM_IT_UPDATE)==SET)//溢出中断
173     {
174         usmart_dev.scan();    //执行usmart扫描
175         __HAL_TIM_SET_COUNTER(&TIM4_Handler,0);;    //清空定时器的CNT
176         __HAL_TIM_SET_AUTORELOAD(&TIM4_Handler,100);//恢复原来的设置
177     }
178     __HAL_TIM_CLEAR_IT(&TIM4_Handler, TIM_IT_UPDATE);//清除中断标志位
179 }
180 
181 //使能定时器4,使能中断.
182 void Timer4_Init(u16 arr,u16 psc)
183 { 
184     //定时器4
185     __HAL_RCC_TIM4_CLK_ENABLE();
186     HAL_NVIC_SetPriority(TIM4_IRQn,0,0);    //设置中断优先级,抢占优先级0,子优先级0
187     HAL_NVIC_EnableIRQ(TIM4_IRQn);          //开启ITM4中断    
188     
189     TIM4_Handler.Instance=TIM4;                          //通用定时器4
190     TIM4_Handler.Init.Prescaler=psc;                     //分频
191     TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
192     TIM4_Handler.Init.Period=arr;                        //自动装载值
193     TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
194     HAL_TIM_Base_Init(&TIM4_Handler);
195     HAL_TIM_Base_Start_IT(&TIM4_Handler); //使能定时器4和定时器4中断                      
196 }
197  
198 
199 #endif
200 ////////////////////////////////////////////////////////////////////////////////////////
201 //初始化串口控制器
202 //sysclk:系统时钟(Mhz)
203 void usmart_init(u8 sysclk)
204 {
205 #if USMART_ENTIMX_SCAN==1
206     Timer4_Init(64535,(u32)sysclk*100-1);//分频,时钟为10K ,100ms中断一次,注意,计数频率必须为10Khz,以和runtime单位(0.1ms)同步.
207 #endif
208     usmart_dev.sptype=1;    //十六进制显示参数
209 }        
210 //从str中获取函数名,id,及参数信息
211 //*str:字符串指针.
212 //返回值:0,识别成功;其他,错误代码.
213 u8 usmart_cmd_rec(u8*str) 
214 {
215     u8 sta,i,rval;//状态     
216     u8 rpnum,spnum;
217     u8 rfname[MAX_FNAME_LEN];//暂存空间,用于存放接收到的函数名  
218     u8 sfname[MAX_FNAME_LEN];//存放本地函数名
219     sta=usmart_get_fname(str,rfname,&rpnum,&rval);//得到接收到的数据的函数名及参数个数      
220     if(sta)return sta;//错误
221     for(i=0;i<usmart_dev.fnum;i++)
222     {
223         sta=usmart_get_fname((u8*)usmart_dev.funs[i].name,sfname,&spnum,&rval);//得到本地函数名及参数个数
224         if(sta)return sta;//本地解析有误      
225         if(usmart_strcmp(sfname,rfname)==0)//相等
226         {
227             if(spnum>rpnum)return USMART_PARMERR;//参数错误(输入参数比源函数参数少)
228             usmart_dev.id=i;//记录函数ID.
229             break;//跳出.
230         }    
231     }
232     if(i==usmart_dev.fnum)return USMART_NOFUNCFIND;    //未找到匹配的函数
233      sta=usmart_get_fparam(str,&i);                    //得到函数参数个数    
234     if(sta)return sta;                                //返回错误
235     usmart_dev.pnum=i;                                //参数个数记录
236     return USMART_OK;
237 }
238 //usamrt执行函数
239 //该函数用于最终执行从串口收到的有效函数.
240 //最多支持10个参数的函数,更多的参数支持也很容易实现.不过用的很少.一般5个左右的参数的函数已经很少见了.
241 //该函数会在串口打印执行情况.以:"函数名(参数1,参数2...参数N)=返回值".的形式打印.
242 //当所执行的函数没有返回值的时候,所打印的返回值是一个无意义的数据.
243 void usmart_exe(void)
244 {
245     u8 id,i;
246     u32 res;           
247     u32 temp[MAX_PARM];//参数转换,使之支持了字符串 
248     u8 sfname[MAX_FNAME_LEN];//存放本地函数名
249     u8 pnum,rval;
250     id=usmart_dev.id;
251     if(id>=usmart_dev.fnum)return;//不执行.
252     usmart_get_fname((u8*)usmart_dev.funs[id].name,sfname,&pnum,&rval);//得到本地函数名,及参数个数 
253     printf("\r\n%s(",sfname);//输出正要执行的函数名
254     for(i=0;i<pnum;i++)//输出参数
255     {
256         if(usmart_dev.parmtype&(1<<i))//参数是字符串
257         {
258             printf("%c",'"');             
259             printf("%s",usmart_dev.parm+usmart_get_parmpos(i));
260             printf("%c",'"');
261             temp[i]=(u32)&(usmart_dev.parm[usmart_get_parmpos(i)]);
262         }else                          //参数是数字
263         {
264             temp[i]=*(u32*)(usmart_dev.parm+usmart_get_parmpos(i));
265             if(usmart_dev.sptype==SP_TYPE_DEC)printf("%ld",temp[i]);//10进制参数显示
266             else printf("0X%X",temp[i]);//16进制参数显示        
267         }
268         if(i!=pnum-1)printf(",");
269     }
270     printf(")");
271 #if USMART_ENTIMX_SCAN==1
272     usmart_reset_runtime();    //计时器清零,开始计时
273 #endif
274     switch(usmart_dev.pnum)
275     {
276         case 0://无参数(void类型)                                              
277             res=(*(u32(*)())usmart_dev.funs[id].func)();
278             break;
279         case 1://有1个参数
280             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
281             break;
282         case 2://有2个参数
283             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1]);
284             break;
285         case 3://有3个参数
286             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2]);
287             break;
288         case 4://有4个参数
289             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3]);
290             break;
291         case 5://有5个参数
292             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4]);
293             break;
294         case 6://有6个参数
295             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
296             temp[5]);
297             break;
298         case 7://有7个参数
299             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
300             temp[5],temp[6]);
301             break;
302         case 8://有8个参数
303             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
304             temp[5],temp[6],temp[7]);
305             break;
306         case 9://有9个参数
307             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
308             temp[5],temp[6],temp[7],temp[8]);
309             break;
310         case 10://有10个参数
311             res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0],temp[1],temp[2],temp[3],temp[4],\
312             temp[5],temp[6],temp[7],temp[8],temp[9]);
313             break;
314     }
315 #if USMART_ENTIMX_SCAN==1
316     usmart_get_runtime();//获取函数执行时间
317 #endif
318     if(rval==1)//需要返回值.
319     {
320         if(usmart_dev.sptype==SP_TYPE_DEC)printf("=%lu;\r\n",res);//输出执行结果(10进制参数显示)
321         else printf("=0X%X;\r\n",res);//输出执行结果(16进制参数显示)       
322     }else printf(";\r\n");        //不需要返回值,直接输出结束
323     if(usmart_dev.runtimeflag)    //需要显示函数执行时间
324     { 
325         printf("Function Run Time:%d.%1dms\r\n",usmart_dev.runtime/10,usmart_dev.runtime%10);//打印函数执行时间 
326     }    
327 }
328 //usmart扫描函数
329 //通过调用该函数,实现usmart的各个控制.该函数需要每隔一定时间被调用一次
330 //以及时执行从串口发过来的各个函数.
331 //本函数可以在中断里面调用,从而实现自动管理.
332 //如果非ALIENTEK用户,则USART_RX_STA和USART_RX_BUF[]需要用户自己实现
333 void usmart_scan(void)
334 {
335     u8 sta,len;  
336     if(USART_RX_STA&0x8000)//串口接收完成?
337     {                       
338         len=USART_RX_STA&0x3fff;    //得到此次接收到的数据长度
339         USART_RX_BUF[len]='\0';    //在末尾加入结束符. 
340         sta=usmart_dev.cmd_rec(USART_RX_BUF);//得到函数各个信息
341         if(sta==0)usmart_dev.exe();    //执行函数 
342         else 
343         {  
344             len=usmart_sys_cmd_exe(USART_RX_BUF);
345             if(len!=USMART_FUNCERR)sta=len;
346             if(sta)
347             {   
348                 switch(sta)
349                 {
350                     case USMART_FUNCERR:
351                         printf("函数错误!\r\n");
352                                       
353                         break;    
354                     case USMART_PARMERR:
355                         printf("参数错误!\r\n");               
356                         break;                
357                     case USMART_PARMOVER:
358                         printf("参数太多!\r\n");               
359                         break;        
360                     case USMART_NOFUNCFIND:
361                         printf("未找到匹配的函数!\r\n");               
362                         break;        
363                 }
364             }
365         }
366         USART_RX_STA=0;//状态寄存器清空        
367     }
368 }
369 #if USMART_USE_WRFUNS==1     //如果使能了读写操作
370 //读取指定地址的值         
371 u32 read_addr(u32 addr)
372 {
373     return *(u32*)addr;//    
374 }
375 //在指定地址写入指定的值         
376 void write_addr(u32 addr,u32 val)
377 {
378     *(u32*)addr=val;     
379 }
380 #endif
View Code

usart.c(我使用到了三个串口,大家只需看串口1定义的内容即可)

  1 /* USER CODE BEGIN Header */
  2 /**
  3   ******************************************************************************
  4   * @file    usart.c
  5   * @brief   This file provides code for the configuration
  6   *          of the USART instances.
  7   ******************************************************************************
  8   * @attention
  9   *
 10   * Copyright (c) 2023 STMicroelectronics.
 11   * All rights reserved.
 12   *
 13   * This software is licensed under terms that can be found in the LICENSE file
 14   * in the root directory of this software component.
 15   * If no LICENSE file comes with this software, it is provided AS-IS.
 16   *
 17   ******************************************************************************
 18   */
 19     #include <stdio.h>
 20     #include <stdarg.h>
 21     #include <string.h>
 22  
 23 /* USER CODE END Header */
 24 /* Includes ------------------------------------------------------------------*/
 25 #include "usart.h"
 26 /* USER CODE BEGIN 0 */
 27 /**********************************begin************************************************************/
 28 
 29 #pragma import(__use_no_semihosting)             
 30             
 31 struct __FILE 
 32 { 
 33     int handle; 
 34  
 35 }; 
 36  
 37 FILE __stdout;       
 38   
 39 void _sys_exit(int x) 
 40 { 
 41     x = x; 
 42 } 
 43 
 44 int fputc(int ch, FILE *f)
 45 {      
 46    
 47     HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
 48     return ch;
 49     
 50 //    while((USART1->SR&0X40)==0);//
 51 //    USART1->DR = (uint8_t) ch;      
 52 //    return ch;
 53 }
 54 /**********************************end************************************************************/
 55 
 56 /**********************************serial port transmit function begin****************************************************/
 57 /**
 58 
 59 */
 60 
 61 void UsartPrintf(UART_HandleTypeDef USARTx, char *fmt,...)
 62 {
 63  
 64     unsigned char UsartPrintfBuf[256];
 65     va_list ap;
 66     unsigned char *pStr = UsartPrintfBuf;
 67     
 68     va_start(ap, fmt);
 69     vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);                            //
 70     va_end(ap);
 71     
 72     while(*pStr != NULL)
 73     {
 74         HAL_UART_Transmit (&USARTx ,(uint8_t *)pStr++,1,HAL_MAX_DELAY );        
 75     }
 76  
 77 }
 78 /**********************************serial port transmit function end****************************************************/
 79 
 80 //串口1中断服务程序
 81 //注意,读取USARTx->SR能避免莫名其妙的错误       
 82 u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
 83 //接收状态标记:bit15,接收完成标志;bit14:;接收到0x0d;bit13~0,接收到的有效字节数目
 84 u16 USART_RX_STA=0;       //接收状态标记    
 85 u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
 86 
 87 /* USER CODE END 0 */
 88 
 89 UART_HandleTypeDef huart1;
 90 UART_HandleTypeDef huart2;
 91 UART_HandleTypeDef huart3;
 92 
 93 /* USART1 init function */
 94 
 95 void MX_USART1_UART_Init(void)
 96 {
 97 
 98   /* USER CODE BEGIN USART1_Init 0 */
 99 
100   /* USER CODE END USART1_Init 0 */
101 
102   /* USER CODE BEGIN USART1_Init 1 */
103 
104   /* USER CODE END USART1_Init 1 */
105   huart1.Instance = USART1;
106   huart1.Init.BaudRate = 9600;
107   huart1.Init.WordLength = UART_WORDLENGTH_8B;
108   huart1.Init.StopBits = UART_STOPBITS_1;
109   huart1.Init.Parity = UART_PARITY_NONE;
110   huart1.Init.Mode = UART_MODE_TX_RX;
111   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
112   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
113   if (HAL_UART_Init(&huart1) != HAL_OK)
114   {
115     Error_Handler();
116   }
117   /* USER CODE BEGIN USART1_Init 2 */
118   HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE);
119 //该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
120   /* USER CODE END USART1_Init 2 */
121 
122 }
123 /* USART2 init function */
124 
125 void MX_USART2_UART_Init(void)
126 {
127 
128   /* USER CODE BEGIN USART2_Init 0 */
129 
130   /* USER CODE END USART2_Init 0 */
131 
132   /* USER CODE BEGIN USART2_Init 1 */
133 
134   /* USER CODE END USART2_Init 1 */
135   huart2.Instance = USART2;
136   huart2.Init.BaudRate = 9600;
137   huart2.Init.WordLength = UART_WORDLENGTH_8B;
138   huart2.Init.StopBits = UART_STOPBITS_1;
139   huart2.Init.Parity = UART_PARITY_NONE;
140   huart2.Init.Mode = UART_MODE_TX_RX;
141   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
142   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
143   if (HAL_UART_Init(&huart2) != HAL_OK)
144   {
145     Error_Handler();
146   }
147   /* USER CODE BEGIN USART2_Init 2 */
148 
149   /* USER CODE END USART2_Init 2 */
150 
151 }
152 /* USART3 init function */
153 
154 void MX_USART3_UART_Init(void)
155 {
156 
157   /* USER CODE BEGIN USART3_Init 0 */
158 
159   /* USER CODE END USART3_Init 0 */
160 
161   /* USER CODE BEGIN USART3_Init 1 */
162 
163   /* USER CODE END USART3_Init 1 */
164   huart3.Instance = USART3;
165   huart3.Init.BaudRate = 9600;
166   huart3.Init.WordLength = UART_WORDLENGTH_8B;
167   huart3.Init.StopBits = UART_STOPBITS_1;
168   huart3.Init.Parity = UART_PARITY_NONE;
169   huart3.Init.Mode = UART_MODE_TX_RX;
170   huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
171   huart3.Init.OverSampling = UART_OVERSAMPLING_16;
172   if (HAL_UART_Init(&huart3) != HAL_OK)
173   {
174     Error_Handler();
175   }
176   /* USER CODE BEGIN USART3_Init 2 */
177 
178   /* USER CODE END USART3_Init 2 */
179 
180 }
181 
182 void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
183 {
184 
185   GPIO_InitTypeDef GPIO_InitStruct = {0};
186   if(uartHandle->Instance==USART1)
187   {
188   /* USER CODE BEGIN USART1_MspInit 0 */
189 
190   /* USER CODE END USART1_MspInit 0 */
191     /* USART1 clock enable */
192     __HAL_RCC_USART1_CLK_ENABLE();
193 
194     __HAL_RCC_GPIOA_CLK_ENABLE();
195     /**USART1 GPIO Configuration
196     PA9     ------> USART1_TX
197     PA10     ------> USART1_RX
198     */
199     GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
200     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
201     GPIO_InitStruct.Pull = GPIO_NOPULL;
202     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
203     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
204     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
205 
206     /* USART1 interrupt Init */
207     HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
208     HAL_NVIC_EnableIRQ(USART1_IRQn);
209   /* USER CODE BEGIN USART1_MspInit 1 */
210 
211   /* USER CODE END USART1_MspInit 1 */
212   }
213   else if(uartHandle->Instance==USART2)
214   {
215   /* USER CODE BEGIN USART2_MspInit 0 */
216 
217   /* USER CODE END USART2_MspInit 0 */
218     /* USART2 clock enable */
219     __HAL_RCC_USART2_CLK_ENABLE();
220 
221     __HAL_RCC_GPIOA_CLK_ENABLE();
222     /**USART2 GPIO Configuration
223     PA2     ------> USART2_TX
224     PA3     ------> USART2_RX
225     */
226     GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
227     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
228     GPIO_InitStruct.Pull = GPIO_NOPULL;
229     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
230     GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
231     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
232 
233     /* USART2 interrupt Init */
234     HAL_NVIC_SetPriority(USART2_IRQn, 2, 0);
235     HAL_NVIC_EnableIRQ(USART2_IRQn);
236   /* USER CODE BEGIN USART2_MspInit 1 */
237 
238   /* USER CODE END USART2_MspInit 1 */
239   }
240   else if(uartHandle->Instance==USART3)
241   {
242   /* USER CODE BEGIN USART3_MspInit 0 */
243 
244   /* USER CODE END USART3_MspInit 0 */
245     /* USART3 clock enable */
246     __HAL_RCC_USART3_CLK_ENABLE();
247 
248     __HAL_RCC_GPIOB_CLK_ENABLE();
249     /**USART3 GPIO Configuration
250     PB10     ------> USART3_TX
251     PB11     ------> USART3_RX
252     */
253     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
254     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
255     GPIO_InitStruct.Pull = GPIO_NOPULL;
256     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
257     GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
258     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
259 
260     /* USART3 interrupt Init */
261     HAL_NVIC_SetPriority(USART3_IRQn, 3, 0);
262     HAL_NVIC_EnableIRQ(USART3_IRQn);
263   /* USER CODE BEGIN USART3_MspInit 1 */
264 
265   /* USER CODE END USART3_MspInit 1 */
266   }
267 }
268 
269 void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
270 {
271 
272   if(uartHandle->Instance==USART1)
273   {
274   /* USER CODE BEGIN USART1_MspDeInit 0 */
275 
276   /* USER CODE END USART1_MspDeInit 0 */
277     /* Peripheral clock disable */
278     __HAL_RCC_USART1_CLK_DISABLE();
279 
280     /**USART1 GPIO Configuration
281     PA9     ------> USART1_TX
282     PA10     ------> USART1_RX
283     */
284     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
285 
286     /* USART1 interrupt Deinit */
287     HAL_NVIC_DisableIRQ(USART1_IRQn);
288   /* USER CODE BEGIN USART1_MspDeInit 1 */
289 
290   /* USER CODE END USART1_MspDeInit 1 */
291   }
292   else if(uartHandle->Instance==USART2)
293   {
294   /* USER CODE BEGIN USART2_MspDeInit 0 */
295 
296   /* USER CODE END USART2_MspDeInit 0 */
297     /* Peripheral clock disable */
298     __HAL_RCC_USART2_CLK_DISABLE();
299 
300     /**USART2 GPIO Configuration
301     PA2     ------> USART2_TX
302     PA3     ------> USART2_RX
303     */
304     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
305 
306     /* USART2 interrupt Deinit */
307     HAL_NVIC_DisableIRQ(USART2_IRQn);
308   /* USER CODE BEGIN USART2_MspDeInit 1 */
309 
310   /* USER CODE END USART2_MspDeInit 1 */
311   }
312   else if(uartHandle->Instance==USART3)
313   {
314   /* USER CODE BEGIN USART3_MspDeInit 0 */
315 
316   /* USER CODE END USART3_MspDeInit 0 */
317     /* Peripheral clock disable */
318     __HAL_RCC_USART3_CLK_DISABLE();
319 
320     /**USART3 GPIO Configuration
321     PB10     ------> USART3_TX
322     PB11     ------> USART3_RX
323     */
324     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11);
325 
326     /* USART3 interrupt Deinit */
327     HAL_NVIC_DisableIRQ(USART3_IRQn);
328   /* USER CODE BEGIN USART3_MspDeInit 1 */
329 
330   /* USER CODE END USART3_MspDeInit 1 */
331   }
332 }
333 
334 /* USER CODE BEGIN 1 */
335 
336 //串口1中断服务程序 
337 void USART1_IRQHandler(void)                    
338 { 
339     u32 timeout=0;
340     HAL_UART_IRQHandler(&huart1);    //调用HAL库中断处理公用函数
341     
342     timeout=0;
343     while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)//等待就绪
344     {
345      timeout++;////超时处理
346      if(timeout>HAL_MAX_DELAY) break;        
347     
348     }
349      
350     timeout=0;
351     while(HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
352     {
353      timeout++; //超时处理
354      if(timeout>HAL_MAX_DELAY) break;    
355     }
356 } 
357 
358 //串口1回调函数
359 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
360 {
361     if(huart->Instance==USART1)//如果是串口1
362     {
363         if((USART_RX_STA&0x8000)==0)//接收未完成
364         {
365             if(USART_RX_STA&0x4000)//接收到了0x0d
366             {
367                 if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
368                 else USART_RX_STA|=0x8000;    //接收完成了 
369             }
370             else //还没收到0X0D
371             {    
372                 if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
373                 else
374                 {
375                     USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
376                     USART_RX_STA++;
377                     if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收      
378                 }         
379             }
380         }
381 
382     }
383 }
384 
385 /* USER CODE END 1 */
View Code

usart.h

 1 #ifndef __USART_H__
 2 #define __USART_H__
 3 
 4 #ifdef __cplusplus
 5 extern "C" {
 6 #endif
 7 
 8 /* Includes ------------------------------------------------------------------*/
 9 #include "main.h"
10 
11 /* USER CODE BEGIN Includes */
12  #include "delay.h"
13 /* USER CODE END Includes */
14 
15 extern UART_HandleTypeDef huart1;
16 extern UART_HandleTypeDef huart2;
17 extern UART_HandleTypeDef huart3;
18 
19 /* USER CODE BEGIN Private defines */
20 #define usart_debug  huart1        //
21 #define usart_sensor huart2        //
22 #define usart_wifi      huart3    //
23 #define USART_REC_LEN              200      //定义最大接收字节数 200
24 #define RXBUFFERSIZE   1 //缓存大小
25 
26 extern u16 USART_RX_STA;                 //接收状态标记    
27 extern u8 aRxBuffer[RXBUFFERSIZE];//HAL库USART接收Buffer
28 extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
29 /* USER CODE END Private defines */
30 
31 void MX_USART1_UART_Init(void);
32 void MX_USART2_UART_Init(void);
33 void MX_USART3_UART_Init(void);
34 
35 /* USER CODE BEGIN Prototypes */
36 void UsartPrintf(UART_HandleTypeDef USARTx,char *fmt,...);
37 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
38 /* USER CODE END Prototypes */
39 
40 #ifdef __cplusplus
41 }
42 #endif
43 
44 #endif /* __USART_H__ */
View Code

delay.h

 1 #ifndef _DELAY_H
 2 #define _DELAY_H
 3 #include "stm32f4xx.h"  
 4 typedef int32_t  s32;
 5 typedef int16_t s16;
 6 typedef int8_t  s8;
 7 
 8 typedef const int32_t sc32;  
 9 typedef const int16_t sc16;  
10 typedef const int8_t sc8;  
11 
12 typedef __IO int32_t  vs32;
13 typedef __IO int16_t  vs16;
14 typedef __IO int8_t   vs8;
15 
16 typedef __I int32_t vsc32;  
17 typedef __I int16_t vsc16; 
18 typedef __I int8_t vsc8;   
19 
20 typedef uint32_t  u32;
21 typedef uint16_t u16;
22 typedef uint8_t  u8;
23 
24 typedef const uint32_t uc32;  
25 typedef const uint16_t uc16;  
26 typedef const uint8_t uc8; 
27 
28 typedef __IO uint32_t  vu32;
29 typedef __IO uint16_t vu16;
30 typedef __IO uint8_t  vu8;
31 
32 typedef __I uint32_t vuc32;  
33 typedef __I uint16_t vuc16; 
34 typedef __I uint8_t vuc8;  
35 
36 void delay_init(u8 SYSCLK);
37 void delay_ms(u16 nms);
38 void delay_us(u32 nus);
39 
40 #endif
View Code

 

如有问题可评论沟通。整理不易,如有帮助请点赞收藏~