IM1266在STM32F103C8T6下使用心得

前言

毕设用了IM1266模块联网传数据,但是苦于没有资料,做毕设的过程很煎熬的,参考了网上的类似的IM1281B的驱动,修修补补下终于算是做出来了,现在写下此博客,供以后的自己和开发者参考。

代码

初始化函数:

void usart3_init(u32 bound)
{  
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//开启GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能
	//复位串口3
 	USART_DeInit(USART3);
	//GPIO设置
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  	GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  	GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11
	//USART设置
	USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为4800;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_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); //初始化串口	3
	//设置NVIC中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	//清理缓存
	IM266_clearBuf();	
	//使能接收中断
  	USART_ITConfig(USART3, USART_IT_RXNE|USART_IT_IDLE, ENABLE);//开启中断   
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);//开启中断   
	USART_Cmd(USART3, ENAB

中断函数:

vu16  USART3_RX_STA=0;

void USART3_IRQHandler(void)
{
	char Res; //一个一个字节接收数据
  	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  
		{
		  USART_ClearITPendingBit(USART3, USART_IT_RXNE);
			Res =USART_ReceiveData(USART3);				
			if(USART3_RX_STA<USART3_MAX_RECV_LEN)  //接收的字符串
			{
				Rx_Buffer_Pre[USART3_RX_STA]=Res;
				USART3_RX_STA++;			
			}
		}
	//空闲中断,在收完数据后自动发送	
	if(USART_GetITStatus(USART3, USART_IT_IDLE) != SET)  
	{
		receive_finished=1;
		USART_ClearITPendingBit(USART3, USART_IT_IDLE);
	}	
	USART3->SR;
	USART3->DR;
//	DEBUG_LOG("接收到IM1266数据");
} 

读写函数:

//3:(地址:01H 命令:03H 数据长度:20H)+32:(数据段4x8=32)+2(CRC校验)=37:实际长度 
unsigned char	Tx_Buffer_Pre[8]; 
unsigned char	Rx_Buffer_Pre[37];
//存放默认单位的数据:0.1V 0.001A等
unsigned char	Read_ID=0x01;
unsigned long	Voltage_data;
unsigned long 	Current_data;
unsigned long 	Power_data;
unsigned long 	Energy_data;
unsigned long 	Pf_data;
unsigned long 	CO2_data;
unsigned long 	Temp_data;
unsigned long 	HZ;
//存放常见单位的数据:1V 1A等
float Voltage_data_F;
float Current_data_F;
float Power_data_F;
float Energy_data_F;
float Pf_data_F;
float CO2_data_F;
float Temp_data_F;
float HZ_F;

int	i=8;//此次发送数据的长度
int j=0;
int receive_finished;//完成标志位
int read_enable=0;	//可读标志位
int reveive_numbe=37;//接收数据总长度
//自带
unsigned int calccrc(unsigned char crcbuf,unsigned int crc)
{
	unsigned char i;
	unsigned char chk;
	crc=crc^crcbuf; 
	for(i=0;i<8;i++)
		{
			chk=( unsigned char)(crc&1);
			crc=crc>>1;
			crc=crc&0x7fff; 
			if (chk==1) crc=crc^0xa001;
			crc=crc&0xffff;
		}
		return crc;
}
//自带
unsigned int chkcrc(unsigned char *buf,unsigned char len)
{
	unsigned char hi,lo; 
	unsigned int i;
	unsigned int crc;
	crc=0xFFFF; 
	for(i=0;i<len;i++)
	{
		crc=calccrc(*buf,crc); 
		buf++;
	}
	hi=( unsigned char)(crc%256);
	lo=( unsigned char)(crc/256);
	crc=(((unsigned int)(hi))<<8)|lo;
	return crc;
}	
//修改 只需更改Tx_Buffer_Pre即可实现其他指令
void read_data(void)
{
			union	crcdata
			{
			unsigned int word16; 
			unsigned char	byte[2];
			}crcnow;
			
			if(read_enable==1)	// 到时间读数据
			{
				read_enable=0;
				Tx_Buffer_Pre[0]=Read_ID;	//模块的 ID 号,默认 ID 为 0x01 
				Tx_Buffer_Pre[1]=0x03;
				Tx_Buffer_Pre[2]=0x00; 
				Tx_Buffer_Pre[3]=0x48;
				Tx_Buffer_Pre[4]=0x00; 
				Tx_Buffer_Pre[5]=0x08; 
				crcnow.word16=chkcrc(Tx_Buffer_Pre,6);
				Tx_Buffer_Pre[6]=crcnow.byte[1];	//CRC 效验低字节在前
				Tx_Buffer_Pre[7]=crcnow.byte[0];

			}
																
			for(j=0;j<i;j++)					//循环发送数据01 03 00 48 00 08 C4 1A
			{
				while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //串口三 循环发送,直到发送完毕   
				USART_SendData(USART3,Tx_Buffer_Pre[j]);
			}
//			DEBUG_LOG("发送IM1266读数据命令");
}
//修改
void Analysis_data(void)
	{	
		union	crcdata
		{
		unsigned int word16;
		unsigned char	byte[2];
		}crcnow;
			
		if(receive_finished==1)	//接收完成
		{
//			reveive_numbe=USART3_RX_STA;
			receive_finished=0; 
			
				if((Rx_Buffer_Pre[0]==0x01)||(Rx_Buffer_Pre[0]==0x00))	//确认 ID 正确
			{
					printf("\r\n确认 ID 正确\r\n");//串口一来打印接受电压值
					crcnow.word16=chkcrc(Rx_Buffer_Pre,reveive_numbe-2);	
				if((crcnow.byte[0]==Rx_Buffer_Pre[reveive_numbe-1])&&(crcnow.byte[1]==Rx_Buffer_Pre[reveive_numbe-2]))//确认 CRC 校验正确
				{
//					printf("\r\n%d\r\n", USART3_RX_STA);
					DEBUG_LOG("==================================================================================");
					Voltage_data=(((unsigned long)(Rx_Buffer_Pre[3]))<<24)|(((unsigned long)(Rx_Buffer_Pre[4]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[5]))<<8)|Rx_Buffer_Pre[6];
					Voltage_data_F=(float)(Voltage_data*0.0001);
					printf("电压:%.4lf V\r\n",Voltage_data_F);//串口一来打印电压
					
					Current_data=(((unsigned long)(Rx_Buffer_Pre[7]))<<24)|(((unsigned long)(Rx_Buffer_Pre[8]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[9]))<<8)|Rx_Buffer_Pre[10];
					Current_data_F=(float)(Current_data*0.0001);
					printf("电流:%.4lf A\r\n",Current_data_F);//串口一来打印电流
					
					Power_data=	(((unsigned	long)(Rx_Buffer_Pre[11]))<<24)|(((unsigned long)(Rx_Buffer_Pre[12]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[13]))<<8)|Rx_Buffer_Pre[14];
					Power_data_F=(float)(Power_data*0.0001);
					printf("功率:%.4lf W\r\n",Power_data_F);//串口一来打印功率
					
					Energy_data=(((unsigned	long)(Rx_Buffer_Pre[15]))<<24)|(((unsigned long)(Rx_Buffer_Pre[16]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[17]))<<8)|Rx_Buffer_Pre[18];
					Energy_data_F=(float)(Energy_data*0.0001);
					printf("电能:%.4lf KWh\r\n",Energy_data_F);//串口一来打印电能
					
					Pf_data=		(((unsigned	long)(Rx_Buffer_Pre[19]))<<24)|(((unsigned long)(Rx_Buffer_Pre[20]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[21]))<<8)|Rx_Buffer_Pre[22];
					Pf_data_F=(float)(Pf_data*0.001);
					printf("功率因数:%.3lf \r\n",Pf_data_F); //串口一来打印接受功率因数
					
					CO2_data=		(((unsigned long)(Rx_Buffer_Pre[23]))<<24)|(((unsigned long)(Rx_Buffer_Pre[24]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[25]))<<8)|Rx_Buffer_Pre[26];
					CO2_data_F=(float)(CO2_data*0.0001);
					printf("二氧化碳:%.4lf Kg\r\n",CO2_data_F);//串口一来打印接受二氧化碳
					
					Temp_data=	(((unsigned long)(Rx_Buffer_Pre[27]))<<24)|(((unsigned long)(Rx_Buffer_Pre[28]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[29]))<<8)|Rx_Buffer_Pre[30];
					Temp_data_F=(float)(Temp_data*0.01);
					printf("温度:%.2lf °C\r\n",Temp_data_F);//串口一来打印接受二氧化碳
					
					HZ=					(((unsigned long)(Rx_Buffer_Pre[31]))<<24)|(((unsigned long)(Rx_Buffer_Pre[32]))<<16)|(((unsigned	long)(Rx_Buffer_Pre[33]))<<8)|Rx_Buffer_Pre[34];
					HZ_F=(float)(HZ*0.01);
					printf("赫兹:%.2lf HZ\r\n",HZ_F);//串口一来打印接受单相交流电的赫兹
					DEBUG_LOG("==================================================================================");
					
					USART3_RX_STA=0;
				}
				else printf("// CRC 校验错误\r\n");
			}
		}
			else printf("\r\nreceive_finished标志位为0\r\n");
	}

 void IM266_clearBuf(void)  //清空USART3_RX_BUF内存 
 {
	 int i;
   for(i=0;i<37;i++)
			  Rx_Buffer_Pre[i]=0;
 }

主函数

 int main(void)
 {	
 	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	usart3_init(4800); //IM1266通讯串口
	DEBUG_LOG("UART3初始化			[OK]");

	while(1)
	{
		read_enable=1;		//读数据使能
		read_data();			//读IM1266数据-中断接收数据-使能完成标志位
		delay_ms(2000);		//等待中断传输
		if(receive_finished)
		{
			Analysis_data();
			receive_finished=0;
		}
	}
}

上图

用PC的效果:
请添加图片描述
串口调试的效果:
请添加图片描述
小程序演示的效果:
请添加图片描述
数据能正常能读取

感谢 良心不痛吗 关于IM1281B的代码,给了很大启发

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脑机超频

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值