使用 C++ 语言给 STM32 编写一个 Usart 类
我使用的STM32芯片:STM32F103ZET6
我们使用的STM32库版本:V3.5.0
注意:
想学习本套 STM32 C++编程 的专栏是有点门槛的。你需要有一点点 STM32 基础 和 一点点 C++ 语言基础。
完整的STM32 C++ Usart类 的下载地址可以在本篇博客的最下面找到。
Usart.cpp
#include "Usart.h"
#include "Gpio.h"
using namespace stm32f10x;
//2015-9-1 00:47:46 Usart2, Uart4,5 没有测试
//_______初始化部分______________
Usart::Usart(USART_TypeDef* USARTx, uint32_t USART_BaudRate, uint32_t NVIC_PriorityGroup,
uint8_t NVIC_IRQChannelPreemptionPriority, uint8_t NVIC_IRQChannelSubPriority)
:usartx(USARTx),baudRate(USART_BaudRate),nvicPriorityGroup(NVIC_PriorityGroup),
preemptionPriority(NVIC_IRQChannelPreemptionPriority), subPriority(NVIC_IRQChannelSubPriority){
initialize();
}
void Usart::initialize(){
Gpio txd,rxd;
switch((uint32_t)usartx){
case (uint32_t)USART1: txd = Gpio(PA,9,GM_AFPP); rxd=Gpio(PA,10,GM_IN_FLOATING); break;
case (uint32_t)USART2: txd = Gpio(PA,2,GM_AFPP); rxd=Gpio(PA,3,GM_IN_FLOATING); break;
case (uint32_t)USART3: txd = Gpio(PB,10,GM_AFPP); rxd=Gpio(PB,11,GM_IN_FLOATING); break;
case (uint32_t)UART4: txd = Gpio(PC,10,GM_AFPP); rxd=Gpio(PC,11,GM_IN_FLOATING); break;
case (uint32_t)UART5: txd = Gpio(PC,12,GM_AFPP); rxd=Gpio(PD,2,GM_IN_FLOATING); break;
}
//打开USARTx时钟
if((uint32_t)usartx < APB2PERIPH_BASE){
uint32_t RCC_APB1Periph = (uint32_t)(1<< ( ((uint32_t)usartx-APB1PERIPH_BASE)>>10));
RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
}
else{
uint32_t RCC_APB2Periph = (uint32_t)(1<< ( ((uint32_t)usartx-APB2PERIPH_BASE)>>10));
RCC_APB2PeriphClockCmd(RCC_APB2Periph, ENABLE);
}
USART_InitTypeDef USART_InitStructure;
//配置USARTx
USART_InitStructure.USART_BaudRate = baudRate; //波特率可以通过地面站配置
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_Tx | USART_Mode_Rx; //发送、接收使能
USART_Init(usartx, &USART_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(nvicPriorityGroup);
switch((uint32_t)usartx){
case (uint32_t)USART1: NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; break;
case (uint32_t)USART2: NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; break;
case (uint32_t)USART3: NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; break;
case (uint32_t)UART4: NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; break;
case (uint32_t)UART5: NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; break;
}
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preemptionPriority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = subPriority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//使能接收中断
USART_ITConfig(usartx, USART_IT_RXNE, ENABLE);
//使能USARTx
USART_Cmd(usartx, ENABLE);
}
//_________初始化部分end___________________
//_________发送数据部分______________________
//////////发送字符串
void Usart::print(const char* pfmt, ...){
double vargflt = 0;
int vargint = 0;
char* vargpch = NULL;
char vargch = 0;
va_list vp;
va_start(vp, pfmt);
while(*pfmt){
if(*pfmt == '%'){
switch(*(++pfmt)){
case 'c':
vargch = va_arg(vp, int);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
print((char)vargch);
break;
case 'd':
case 'i':
vargint = va_arg(vp, int);
printdec(vargint);
break;
case 'f':
vargflt = va_arg(vp, double);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
print(vargflt);
break;
case 's':
vargpch = va_arg(vp, char*);
print(vargpch);
break;
case 'b':
case 'B':
vargint = va_arg(vp, int);
printbin(vargint);
break;
case 'x':
case 'X':
vargint = va_arg(vp, int);
printhex(vargint);
break;
case '%':
print('%');
break;
case 'o':
case 'O':
vargint = va_arg(vp, int);
printoct(vargint);
break;
default:
break;
}
pfmt++;
}
else{
print(*pfmt++);
}
}
va_end(vp);
}
//2015年9月3日11:41:40 支持 打印 0 和 负数
void Usart::printdec(int dec){
static uint8_t dp = 0;
static int _dec;
if(dec<=0 && dp == 0){
if(dec == 0){
print('0');
return ;
}else{
print('-');
dec = -dec;
}
}
if(dp ==0 ){
dp = 1;
_dec = dec;
}
if(dec==0){
return; }
printdec(dec/10);
print( (char)(dec%10 + '0'));
if(_dec == dec)
dp = 0;
}
void Usart::printflt(double flt){
int tmpint = 0;
tmpint = (int)flt;
printdec(tmpint);
print('.');
flt = flt - tmpint;
flt = flt<0?-flt:flt;
tmpint = (int)(flt * 1000000);
printdec(tmpint);
}
void Usart::printbin(int bin){
if(bin == 0){
//printstr("0b");
return; }
printbin(bin/2);
print( (char)(bin%2 + '0'));
}
void Usart::printhex(int hex){
if(hex==0){
//printstr("0x");
return; }
printhex(hex/16);
if(hex%16 < 10)
print((char)(hex%16 + '0'));
else
print((char)(hex%16 - 10 + 'a' ));
}
void Usart::printoct(int oct){
if(oct==0){
//printstr("8JinZhi");
return;
}
printoct(oct/8);
print((char)(oct%8 + '0'));
}
//________2015-8-31 02:57:51
void Usart::print(char ch){
USART_SendData(usartx, ch); /*发送单个数据 */
while(USART_GetFlagStatus(usartx, USART_FLAG_TXE)==RESET);/* 检测指定的USART标志位 即RESET=1时 发送完成*/
}
void Usart::print(const unsigned char *str){
while(*str){
USART_SendData(usartx, *str); /*发送单个数据 */
while(USART_GetFlagStatus(usartx, USART_FLAG_TXE)==RESET);/* 检测指定的USART标志位 即RESET=1时 发送完成*/
str++;
}
}
void Usart::print(int val, Format format){
switch((uint8_t)format){
case (uint8_t)DEC:
printdec(val);
break;
case (uint8_t)HEX:
printhex(val);
break;
case (uint8_t)BIN:
printbin(val);
break;
case (uint8_t)OCT:
printoct(val);
break;
default:
break;
}
}
int Usart::pow(int a, int n){
int sum = 1;
while(n--){
sum = sum*a;
}
return sum;
}
void Usart::print(double flt, uint8_t para){
int tmpint = 0;
tmpint = (int)flt;
printdec(tmpint);
print('.');
flt = flt - tmpint;
flt = flt<0?-flt:flt;
tmpint = (int)(flt * pow(10, para));
printdec(tmpint);
}
void Usart::println(const char* pfmt, ...){
double vargflt = 0;
int vargint = 0;
char* vargpch = NULL;
char vargch = 0;
va_list vp;
va_start(vp, pfmt);
while(*pfmt){
if(*pfmt == '%'){
switch(*(++pfmt)){
case 'c':
vargch = va_arg(vp, int);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
print((char)vargch);
break;
case 'd':
case 'i':
vargint = va_arg(vp, int);
printdec(vargint);
break;
case 'f':
vargflt = va_arg(vp, double);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
print(vargflt);
break;
case 's':
vargpch = va_arg(vp, char*);
print(vargpch);
break;
case 'b':
case 'B':
vargint = va_arg(vp, int);
printbin(vargint);
break;
case 'x':
case 'X':
vargint = va_arg(vp, int);
printhex(vargint);
break;
case '%':
print('%');
break;
case 'o':
case 'O':
vargint = va_arg(vp, int);
printoct(vargint);
break;
default:
break;
}
pfmt++;
}
else{
print(*pfmt++);
}
}
va_end(vp);
print("
");
}
void Usart::println(double flt, uint8_t para){
print(flt, para);
print("
");
}
void Usart::println(int val, Format format){
print(val, format);
print("
");
}
//////发送数据
void Usart::write(u8 val){
print((char)val);
}
//请注意 int8_t,vs8 原型都是 int(32位的) 并不是char(8位的)
void Usart::write(char val){
print((char)val);
}
void Usart::write(u16 val){
print((char)BYTE1(val));
print((char)BYTE0(val));
}
void Usart::write(vs16 val){
print((char)BYTE1(val));
print((char)BYTE0(val));
}
void Usart::write(u32 val){
print((char)BYTE3(val));
print((char)BYTE2(val));
print((char)BYTE1(val));
print((char)BYTE0(val));
}
void Usart::write(vs32 val){
print((char)BYTE3(val));
print((char)BYTE2(val));
print((char)BYTE1(val));
print((char)BYTE0(val));
}
//_________发送部分end______________________
unsigned char Usart::read(){
unsigned char ch;
if(USART_GetITStatus(usartx, USART_IT_RXNE) != RESET){
ch = USART_ReceiveData(usartx);
print("%c",ch);
}
return ch;
}
Usart.h
#ifndef __USART_H_
#define __USART_H_
#include "stm32f10x.h"
#include <stdio.h>
#include <stdarg.h>
namespace stm32f10x
{
enum Format
{//2, 10 , 8, 16 进制
BIN=1, DEC, OCT, HEX,
};
#define BYTE0(dwTemp) (*(char *)(&dwTemp))
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
class Usart{
public:
//初始化部分
Usart(USART_TypeDef* USARTx = USART1,
uint32_t USART_BaudRate = 115200,
uint32_t NVIC_PriorityGroup = NVIC_PriorityGroup_0,
uint8_t NVIC_IRQChannelPreemptionPriority = 0,
uint8_t NVIC_IRQChannelSubPriority = 1
);
void initialize();
//发送字符串部分
void print(const char* ch, ...);
void print(int val, Format format= DEC);
void print(double flt, uint8_t para = 2);
void println(const char* ch = "", ...);
void println(int val, Format format= DEC);
void println(double flt, uint8_t para = 2);
//发送数据部分
void write(u8 val); //unsigned char, uint8_t
void write(char val); //char //请注意 int8_t,vs8 原型都是 int(32位的) 并不是char(8位的)
void write(u16 val); //uint16_t
void write(vs16 val); //int16_t
void write(u32 val); //unsigned int, uint32_t
void write(vs32 val); //int, int32, int8_t, vs8
//接收数据部分
unsigned char read();
private:
USART_TypeDef* usartx;
uint32_t baudRate;
uint32_t nvicPriorityGroup;
uint8_t preemptionPriority;
uint8_t subPriority;
void print(char ch);
void print(const unsigned char *str);
void printdec(int dec);
void printflt(double flt);
void printbin(int bin);
void printhex(int hex);
void printoct(int oct);
int pow(int a, int n);
};
}
#endif
main.cpp
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "Usart.h"
using namespace stm32f10x;
/* Private functions ---------------------------------------------------------*/
Usart Serial(USART1, 115200);
// Usart Serial;
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
// uint8_t val8 = 0x33;
// uint32_t val32 = 0x21122112;
while(1){
Serial.println("1.%f",-123.4545);
Serial.println("2.%o",123);
Serial.println("3.print: %c", 'c');
Serial.println("4.print: %s", "string test");
Serial.println("5.print: %b, %d", 0x12345ff, 4343);
Serial.println("%d", -4343);
Serial.println("6.print: %x", 0xa1d);
// Serial.println("7.print: %%");
// Serial.println(1234, BIN);
// Serial.println(12.3434, 4);
// Serial.write(val8);
// Serial.write(val32);
// Serial.println();
}
}
搞定
你可以到这里下载我已经做好的 STM32 C++ Usart类:
百度云 链接:http://pan.baidu.com/s/1bpbZ2MV 密码:esam
也可以在CSDN里面下载:http://download.csdn.net/detail/github_35160620/9623335
小结:
下一讲,我们来使用 C++ 语言,创建一个 STM32 的 Adc 类。