STM32 C++ 串口通信

STM32 C++ 串口通信

  • STM32 C++编程设置
    • 注意
  • main.cpp 代码
    • 注意
  • 运行结果
  • 补充
  • 补充二
  • 补充三
  • 源码

STM32 C++编程设置

参考:STM32的C++的简单实现(MDK5 STM32F103大容量系列)
keil编译环境支持C++编译,所以keil不需要做任何修改

注意

涉及中断的服务函数必须用 extern “C” 作前缀,因为stm32的中断服务名是由汇编的启动代码内的向量表决定的,汇编不认得C++的函数名的链接符号。

main.cpp 代码

#include "math.h"
#include "string.h"
#include "ctype.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "stdio.h"

extern u16 USART_RX_STA;

//#ifndef true
//	#define true 1
//#endif
//#ifndef false
//	#define false 0
//#endif

#define DEBUG_INFO

class USARTProc{
public:
	USARTProc(){
		m_usart=USART1;
		m_bstate=false;
		memset(receive_data, '\0', RECIVE_DATA_MAX_LEN);
	}
	USARTProc(USART_TypeDef* usart){
		m_usart=usart;
		m_bstate=false;
		memset(receive_data, '\0', RECIVE_DATA_MAX_LEN);
	}
	
	int GetData() const{
		return m_data;
	}
	bool GetState() const{
		return m_bstate;
	}
	const char* GetReceiveStr(){
		return receive_data;
	}
	USART_TypeDef* GetUsart(){
		return m_usart;
	}
	
	// ͨ¹ý´®¿Ú»ñµÃÊý×Ö
	void ReceiveNumber(){
    while(1){
			m_bstate=false;
			if(USART_RX_STA & 0x8000){
				int r, data; 						// 用于数据转换
				u16 len;
				bool bsign=true; 				// 数据符号 true --> +, false --> -
				len = USART_RX_STA & 0x3fff;
				r = len;
        m_data = 0;
				memset(receive_data, '\0', RECIVE_DATA_MAX_LEN);
				
        for(int t = 0; t < len; t++){
					// 若注释以下两行代码,会出现连续输出的BUG
					USART_SendData(m_usart, USART_RX_BUF[t]);
					while(USART_GetFlagStatus(m_usart, USART_FLAG_TC) != SET){}
						receive_data[t] = USART_RX_BUF[t];
						if(receive_data[t]=='-'){
							bsign = false;
							data = 0;
						//}else if(isdigit(receive_data[t])){
						}else{
							data = (int)receive_data[t] - 48;
						}
						r = r - 1;
						m_data = m_data + data * (pow(10.0, r));
				}
				
				if(!bsign)
					m_data = -m_data;
				
				USART_RX_STA = 0;
				m_bstate=true;
				
				#ifdef DEBUG_INFO
					USARTx_printf(m_usart, "\r\n");
					USARTx_printf(m_usart, "data=%d, bsign=%d, bstate=%d \r\n", m_data, bsign, m_bstate);
				#endif
				
				break;
			}
		}
	}
private:
	enum {RECIVE_DATA_MAX_LEN=60};
private:
	char receive_data[RECIVE_DATA_MAX_LEN];
	int m_data; 			// 数据
	bool m_bstate; 		// 是否接受到数据
private:
	USART_TypeDef * m_usart;
};

int main(void)
{		

	delay_init();	    	 			  
	NVIC_Configuration(); 	 	
	uart_init(9600);	 
// 	LED_Init();	
//	KEY_Init(); 
	USARTProc usartproc;
 	while(1)
	{
		usartproc.ReceiveNumber();
		if(usartproc.GetState()){
			USARTx_printf(usartproc.GetUsart(), "data=%d, str=%s \r\n", usartproc.GetData(), usartproc.GetReceiveStr());
		}
  }
}

注意

若仅改变上述代码,编译不会出错,但由于找不到中断函数的入口,会导致阻塞,需要在中断函数处添加 extern "C"

extern "C" void USART1_IRQHandler(void) // 其他入口函数同样处理

运行结果

STM32 C++ 串口通信_第1张图片

补充

针对extern "C"的另一种实现方式。

#ifdef __cplusplus
extern "C" {
#endif
void USART1_IRQHandler(void)  
{
	...
}
#ifdef __cplusplus
}
#endif

补充二

基于CPP编写程序时,不支持重定义fputc函数,所以不能使用printf,会导致阻塞。当使用到串口通信时,遇到开发板没有任何反应时,应当检查是否是串口程序的原因。

补充三

stm32f10x_conf.h为工程配置文件,为避免工程编译无用外设文件,stm32f10x_conf.h中注释了大部分外设头文件,所以当用到新的外设时,需要在该文件中修改对应包含的头文件。也可以直接在对应的文件中包含对应外设的头文件。
在用到新的外设时还需要在工程中添加对应的CPP文件。
当编译出现undefined symbol错误的时候,是由于找不到对应的实现,所以需要添加对应的c/cpp文件;
当编译出现identifier undefined错误的时候,是由于找不到对应的声明,所以需要添加对应的h文件;
若出现均正确添加但仍编译错误时,可考虑将工程中涉及到的源文件重新添加的方式纠错。

源码

源码地址

你可能感兴趣的:(c++,stm32,嵌入式)