初级会员

- 积分
- 187
- 金钱
- 187
- 注册时间
- 2014-6-3
- 在线时间
- 0 小时
|
各位用战舰版学习STM32单片机的朋友们你你们好!
大家学完了原子哥的STM32战舰版程序了没?我特为战舰版的每一个例程开发了新的程序,完全不同于原子哥的,
全是为了工程项目服务的,能直接应用于工程,全新的开发方式,全文注释,想了解吗?
例如SD卡的SDIO访问,整个系统的总线控制等等,以及I/O口有全新管理方法,大家看了之后,必定能力极大提升,
能更好的掌握STM32103系列单片机的使用;
本人基于战舰版的板子,开发了STM32103ZET6除以太网的所有例程,全可以直接应用于工程项目,也就是说模块化了;
下面提供一个例程,用MySprintf函数对总线进行管理;
本例程是在UCOS上运行的;
大家还在为在嵌入式系统中实现printf函数而寻找方法吗?
想了解printf函数到底是怎样实现的吗?
有用printf函数向任意总线发送数据吗?
因为大多数移植都是向串口发送数据,如果想要用printf函数向SPI总线,CAN总线发送数据,怎样实现?
想不想向总线发送完数据之后,由总线自动将其缓冲区内的数据发送完毕?
看完本例程之后,大家就会全明了;
MySprintf函数说明:
1)函数原型:
MySprintf(总线号,"格式控字符串",参数列表)
2)格式控制字符串
字符数据输出:
%c,%C 输出单个字符
%s,%S 输出字符串
%p%s,%P%s,%P%s 从字符串起始地址开如输出指定长度个字符,用于将一个指定的数组中的多少个元素发送出去;
%y%s,%y%S 从字符串起始地址开如输出指定长度个字符,用于将一个指定的数组中的多少个元素发送出去;
%Y%s,%Y%S 从字符串的指定的字符开始,开始向字符串起始地址方向发送数据;
数值型数据输出:
注意:在输出数据型数据时,输出参数必须与格式说明符对应的数据类型一致,最好用数据类型强制转换;
%d,%D,%i,%I, 以10进制的形式输出符号数;对应的数据类型为 int
%u 以10进制的形式发送无符号数;对应的数据类型为 unsigned int
%x,%X, 以16进制的形式发送无符号数;对应的数据类型为 unsigned int
%B,%b, 以2进制的形式发送无符号数;对应的数据类型为 unsigned int
%O,%o 以8进制的形式发送无符号数;对应的数据类型为 unsigned int
%f 以10进制的形式发送实型数;对应的数据类型为 double
如果需要输出长整型,则在相应的格式说明符前加l或者L,如:%lx,
但是需要注意的是,其所对应的参数必须用 unsigned long long 强制说明;
字符测试:
MySprintf(USART1S,"%p%s\r\n",1,"WangPingVeryGood!"); /* 从WangPingVeryGood!输出1个字符,即W */
MySprintf(USART1S,"%p%s\r\n",2,"WangPingVeryGood!"); /* 从WangPingVeryGood!输出2个字符,即Wa */
MySprintf(USART1S,"%y%s\r\n",1,"WangPingVeryGood!");/* 从WangPingVeryGood!输出1个字符,即W */
MySprintf(USART1S,"%y%s\r\n",2,"WangPingVeryGood!");/* 从WangPingVeryGood!输出2个字符,即Wa */
MySprintf(USART1S,"%Y%s\r\n",16,"WangPingVeryGood!");/* 从WangPingVeryGood!第16个字符开始,即先输出d */
/* 输出结果为dooGyreVgniPgnaw */
MySprintf(USART1S,"%Y%s\r\n",15,"WangPingVeryGood!");/* 从WangPingVeryGood!第15个字符开始,即先输出o */
/* 输出结果为ooGyreVgniPgnaw */
数值测试:
MySprintf(USART1S,"Test19=%f\r\n",0.0123);
详细测试,详见
STM32F103ZET6TestMySprintfAllNew\APP下的CommnicationService.c
请打开串口调试助手sscom33查看测试结果;
本例中还包含GPIO的管理,USART1串口程序,可直接应用于工程,请查看源码!
关于战舰版的STM32其它应用,欢迎大家来询;
手机18927587669
/*
* =====================================================================================
* Name: void MySprintf(unsigned char Driver,char *TempFormatString,...)
* Description: 函数功能:
* 入口参数:1)Driver 驱动器
* 2)TempFormatString 从格式控制字符串开始为可变参数
* 出口参数:无
* =====================================================================================
*/
void MySprintf(unsigned char Driver,char *TempFormatString,...){
char *SendCharPoint; /* 存储发送数据 */
unsigned char CharData; /* */
char *FormatString=(void *)0; /* 格式控制指针 */
unsigned char BufferSize=0; /* 缓冲区大小 */
unsigned char Lflag=0;
unsigned char LflagTrue=0; /* %l */
#if MySprintf_DebugEnable==1
unsigned char DebugMode=FALSE;
#endif
va_list vp; /* */
if(Driver>BUS_DEVICE_GROUP)return; /* 设备号不存在,退出 */
if(BusSendFunction[Driver]==(void *)0){ /* 如果指定的设备发送函数不存在,退出 */
return;
}
va_start(vp,TempFormatString); /* 获得格式化输出字符串 */
#if MySprintf_DebugEnable==1
MDriver=Driver; /* 存储设备号 */
MCapflag=0; /* 默认为小写 */
#endif
FormatString=TempFormatString;
while(*FormatString){ /* 直到字符串结束标志符 */
if(*FormatString=='%'||Lflag){ /* 是格式字符串起始字符%,或者已经接收到l/L */
Lflag=FALSE;
switch(*(++FormatString)){ /* */
/* %c,其所对应的参数最好用 int 强制转换 */
case 'c': /* 1)格式为%c */
case 'C':
CharData=va_arg(vp,int); /* 获得%c,所对应的输出参数,必须使用CharData变量,不能用指针 */
MySprintf_PrintChar(Driver,CharData);
/* 向Driver设备发送字符 */
break;
case 'Y':
MHightoLow=TRUE;
case 'y':
case 'P':
case 'p':
BufferSize=va_arg(vp,int);
break;
case 's': /* 3)格式为s% */
case 'S':
SendCharPoint=va_arg(vp,char *);
MySprintf_PrintString(Driver,SendCharPoint,BufferSize);
/* 输出字符串字符 */
BufferSize=0; /* 必须将BufferSize清零 */
break;
case '%': /* 4)格式为%% */
MySprintf_PrintChar(Driver,'%'); /* 输出%号本身 */
break;
default:
#if MySprintf_DebugEnable==1 /* 使能了调试 */
DebugMode=TRUE;
#endif
break;
}
#if MySprintf_DebugEnable==1 /* 使能了调试 */
if(DebugMode){
DebugMode=FALSE;
switch(*FormatString){
case 'l':
case 'L':
Lflag=TRUE; /* 标志接收到l字符 */
LflagTrue=TRUE;
break;
/* %d格式默认为int,因此,参数需用 int 强制转换 */
/* %ld格式默认为 long long int,因此,参数需用 long long int 强制转换 */
case 'd': /* 5)格式为%d */
case 'D':
case 'i':
case 'I':
if(!LflagTrue){
MParameterValue=va_arg(vp,int);
}
else{
LflagTrue=FALSE;
MParameterValue=va_arg(vp,long long int);
}
if(MParameterValue<0){
MParameterValue=-MParameterValue;/* 转换成正值 */
MySprintf_PrintChar(Driver,'-'); /* 向Driver设备发送负号 */
}
MFormat=DEC; /* 格式10进制 */
MFact=10; /* 基数为10 */
MySprintf_PrintFormat();
break;
/* %x,%X,%b,%B,%o,%O,其所对应的参数,最好用 unsigned int 强制说明 */
/* %lx,%LX,%LB,%LO,%lo,其所对应的参数,最好用 unsigned long int 强制说明 */
case 'X': /* 6)%x格式 */
case 'B':
case 'O':
MCapflag=TRUE;
case 'x':
case 'b':
case 'o':
case 'u':
case 'U':
if(!LflagTrue){
MParameterValue=va_arg(vp,unsigned int);
}
else{
LflagTrue=FALSE;
MParameterValue=va_arg(vp,unsigned long long int);
}
if(*FormatString=='x'||*FormatString=='X'){
MFormat=HEX; /* 格式16进制 */
MFact=16; /* 基数为16 */
}
else if(*FormatString=='b'||*FormatString=='B'){
MFormat=BIN; /* 格式2进制 */
MFact=2; /* 基数为2 */
}
else if(*FormatString=='O'||*FormatString=='o'){
MFormat=OCT; /* 格式8进制 */
MFact=8; /* 基数为8 */
}
else if(*FormatString=='u'||*FormatString=='U'){
MFormat=DEC; /* 格式10进制 */
MFact=10; /* 基数为10 */
}
MySprintf_PrintFormat();
break;
/* %f 其所对应的参数最好用 double 进行强制转换 */
case 'f':
case 'F':
MFParameterValue=va_arg(vp,double); /* 获得%f所对应的输出参数 */
if(MFParameterValue<0){ /* 如果是一个负值 */
MySprintf_PrintChar(Driver,'-'); /* 输出负号 */
MFParameterValue=-MFParameterValue; /* 将负值转换正值 */
}
MySprintf_PrintFloatValue(); /* 输出实型数据 */
break;
default:
break;
}
}
#endif
if(!Lflag)FormatString++; /* 如果不是%l,则指向下一个字符, */
}
else{ /* 否则,为普通字符 */
if(!Lflag){
MySprintf_PrintChar(Driver,*FormatString++);
/* 输出普通字符 */
}
}
}
va_end(vp); /* 结束可变参量 */
}
|
|