前言

   老习惯点个题,最近也是比较忙了,很多事情闲了,有时间瞎搞自己组了基于can的温湿度显示其实是比较    
 简单的,也很简陋因为本人还是比较偏软件类的,这个也是一直兴起,代码和硬件本身还是存在很多问题的,
 欢迎大家来讨论,共同进步。

项目分析

   简单的说一下组成吧,由两片stm32f103c8 和 两片tja1050 一个7pin的oled显示屏,和一片aht10组成
 当然还有若干杜邦线,代码的话分为温湿度端,和oled端,当然字如其名,温湿度端实现了温湿度的检测和发
 送到oled端,由bsp_can.c和bsp_i2c.c组成;oled端的话是显示温湿度,由oled.c和can.c组成,目前代码
 还是存在一点小bug的就是显示温湿度小数点以后的数字是没办法显示的,本人也是暂时没有弄了,等闲了在改
 如果你有好的方法欢迎指导我一下,感谢了!
   说一下硬件吧tja1050的TX接PB8,TX接PB9(由于我这个板子PB8,BP9是复用引脚所以你一定要用GPIO_PinR
   emapConfig 函数把 CAN 映射至 PB8、PB9),VCC是需要5v供电的,GND自然接GND着没的说,aht10的VIN接
3.3,GND接GND,SCL接PB6,SDA接PB7 ,还有就是stm32供电的问题,个人建议不要用电脑供电因为之前我电脑
供电一直无法实现通信,电脑供电大概率是因为供电不足吧所以,个人建议你用充电器供电稳妥一点。
    关于can通信我是建议你先用回环测试,如果回环测试成功再进行下一步,不过你要注意的是我使用的stm32
是自带can协议的,也就是说不需要tja1050也是可以实现回环的,回环只是逻辑上的相同,实现can的自循环,所
以当你can回环可用的时候在外接tja1050就可以实现接受数据了的,使用can分析仪的时候H接CAN_H,L接CAN_L,
就没有问题了,当然你是要注意波特率的,每个板子的波特率都是不同的,所以你需要自己查询文档,我的板子的
话 HSE时钟:8MHz ,由于我用的是PLL输入时钟源所以我的can工作时钟是36HZ(这些我相信百度你会找到答案的)
当然我给你个公式 晶振 x  PLL倍频 / APB1分频 / 60 / (1 + 3 + 2) = 0.1 = 100 (K)(结果只是例子你需
要自己根据自身情况来解决),所以我的can的通信波特率是 100 K。

温湿度端

bsp_i2c.c

#include "./bsp_i2c/bsp_i2c.h"
#include "./delay/delay.h"

uint8_t   ack_status=0;
uint8_t   readByte[6];
uint8_t   aht10_status=0;

uint32_t  H1=0;  //Humility
uint32_t  T1=0;  //Temperature

uint8_t  AHT10_OutData[4];
uint8_t  AHT10sendOutData[10] = {0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

float AdcData[4][20];
u8 TempMeasure_Flag;//温度测试次数标志
float AveId[4];//数据测量次数,最多20
float AdcData_Temp[20];//承接温度的中间数据
float AdcData_Humi[20];//承接湿度的中间数据


/******************
*以下为IO口模块I2C配置
******************/


/*
20个数据循环左移1
*/
void ZuoYi(float *arr){
	int i;
	for(i=0;i<19;i++){
		arr[i]=arr[i+1];
	}
}

//将数组arr2的20个数据给数组arr1;
void JiaoHuan(float *arr1,float *arr2) {
	int i;
	for(i=0;i<20;i++){
	arr1[i]= arr2[i];
	}
}



void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	IIC_SCL=1;
	IIC_SDA=1;
 
}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
		SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
	{
    IIC_SCL=0; 
    delay_us(2);
		IIC_SCL=1;
    receive<<=1;
    if(READ_SDA)receive++;   
		delay_us(1); 
  }					 
	if (!ack)
			IIC_NAck();//发送nACK
	else
			IIC_Ack(); //发送ACK   
	return receive;
}
 
void IIC_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)
{
	IIC_Start();  
	
	if(device_addr==0xA0) //eeprom地址大于1字节
		IIC_Send_Byte(0xA0 + ((addr/256)<<1));//发送高地址
	else
		IIC_Send_Byte(device_addr);	    //发器件地址
	IIC_Wait_Ack(); 
	IIC_Send_Byte(addr&0xFF);   //发送低地址
	IIC_Wait_Ack(); 
	IIC_Send_Byte(data);     //发送字节							   
	IIC_Wait_Ack();  		    	   
  IIC_Stop();//产生一个停止条件 
	if(device_addr==0xA0) //
		delay_ms(10);
	else
		delay_us(2);
}
 
uint16_t IIC_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead)  //读寄存器或读数据
{	
		uint16_t data;
		IIC_Start();  
		if(device_addr==0xA0)
			IIC_Send_Byte(0xA0 + ((addr/256)<<1));
		else
			IIC_Send_Byte(device_addr);	
		IIC_Wait_Ack();
		IIC_Send_Byte(addr&0xFF);   //发送低地址
		IIC_Wait_Ack(); 
 
		IIC_Start();  	
		IIC_Send_Byte(device_addr+1);	    //发器件地址
		IIC_Wait_Ack();
		if(ByteNumToRead == 1)//LM75温度数据为11bit
		{
			data=IIC_Read_Byte(0);
		}
		else
			{
				data=IIC_Read_Byte(1);
				data=(data<<8)+IIC_Read_Byte(0);
			}
		IIC_Stop();//产生一个停止条件	    
		return data;
}


/**********
*以下为AHT10的配置I2C
*函数名有IIC和I2C的不同
***********/
void  read_AHT10_once(void)
{
	delay_ms(10);

	reset_AHT10();
	delay_ms(10);

	init_AHT10();
	delay_ms(10);

	startMeasure_AHT10();
	delay_ms(80);

	read_AHT10();
	delay_ms(5);
}


void  reset_AHT10(void)
{

	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("1");
	else printf("1-n-");
	I2C_WriteByte(0xBA);
	ack_status = Receive_ACK();
		if(ack_status) printf("2");
	else printf("2-n-");
	I2C_Stop();

	/*
	AHT10_OutData[0] = 0;
	AHT10_OutData[1] = 0;
	AHT10_OutData[2] = 0;
	AHT10_OutData[3] = 0;
	*/
}



void  init_AHT10(void)
{
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("3");
	else printf("3-n-");	
	I2C_WriteByte(0xE1);
	ack_status = Receive_ACK();
	if(ack_status) printf("4");
	else printf("4-n-");
	I2C_WriteByte(0x08);
	ack_status = Receive_ACK();
	if(ack_status) printf("5");
	else printf("5-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("6");
	else printf("6-n-");
	I2C_Stop();
}



void  startMeasure_AHT10(void)
{
	//------------
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("7");
	else printf("7-n-");
	I2C_WriteByte(0xAC);
	ack_status = Receive_ACK();
	if(ack_status) printf("8");
	else printf("8-n-");
	I2C_WriteByte(0x33);
	ack_status = Receive_ACK();
	if(ack_status) printf("9");
	else printf("9-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("10");
	else printf("10-n-");
	I2C_Stop();
}



void read_AHT10(void)
{
	uint8_t   i;
  u8 dataid;
	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}

	//-------------
	I2C_Start();

	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	if(ack_status) printf("11");
	else printf("11-n-");
	readByte[0]= I2C_ReadByte();
	printf("test0:%d",readByte[0]);
	Send_ACK();

	readByte[1]= I2C_ReadByte();
	printf("test1:%d",readByte[1]);
	Send_ACK();

	readByte[2]= I2C_ReadByte();
	printf("test2:%d",readByte[2]);
	Send_ACK();

	readByte[3]= I2C_ReadByte();
	printf("test3:%d",readByte[3]);
	Send_ACK();

	readByte[4]= I2C_ReadByte();
	printf("test4:%d",readByte[4]);
	Send_ACK();

	readByte[5]= I2C_ReadByte();
	printf("test5:%d",readByte[5]);
	SendNot_Ack();
	//Send_ACK();

	I2C_Stop();

	//--------------
	if( (readByte[0] & 0x68) == 0x08 )
	{
		H1 = readByte[1];
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		H1 = H1>>4;

		H1 = (H1*1000)/1024/1024;

		T1 = readByte[3];
		T1 = T1 & 0x0000000F;
		T1 = (T1<<8) | readByte[4];
		T1 = (T1<<8) | readByte[5];

		T1 = (T1*2000)/1024/1024 - 500;

		AHT10_OutData[0] = (H1>>8) & 0x000000FF;
		AHT10_OutData[1] = H1 & 0x000000FF;

		AHT10_OutData[2] = (T1>>8) & 0x000000FF;
		AHT10_OutData[3] = T1 & 0x000000FF;
		printf("成功了");
	}
	else
	{
		AHT10_OutData[0] = 0xFF;
		AHT10_OutData[1] = 0xFF;

		AHT10_OutData[2] = 0xFF;
		AHT10_OutData[3] = 0xFF;
		printf("失败了");

	}
}




uint8_t  Receive_ACK(void)
{
	uint8_t result=0;
	uint8_t cnt=0;

	IIC_SCL = 0;
	SDA_IN(); 
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);

	while(READ_SDA && (cnt<100))
	{
		cnt++;
	}

	IIC_SCL = 0;
	delay_us(4);

	if(cnt<100)
	{
		result=1;
	}
	return result;
}



void  Send_ACK(void)
{
	SDA_OUT();
	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 0;
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);
	IIC_SCL = 0;
	delay_us(4);

	SDA_IN();
}



void  SendNot_Ack(void)
{
	SDA_OUT();
	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 1;
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);

	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 0;
	delay_us(4);
}


void I2C_WriteByte(uint8_t  input)
{
	uint8_t  i;
	SDA_OUT();
	for(i=0; i<8; i++)
	{
		IIC_SCL = 0;
		delay_ms(5);

		if(input & 0x80)
		{
			IIC_SDA = 1;
			//delaymm(10);
		}
		else
		{
			IIC_SDA = 0;
			//delaymm(10);
		}

		IIC_SCL = 1;
		delay_ms(5);

		input = (input<<1);
	}

	IIC_SCL = 0;
	delay_us(4);

	SDA_IN();
	delay_us(4);
}	


uint8_t I2C_ReadByte(void)
{
	uint8_t  resultByte=0;
	uint8_t  i=0, a=0;

	IIC_SCL = 0;
	SDA_IN();
	delay_ms(4);

	for(i=0; i<8; i++)
	{
		IIC_SCL = 1;
		delay_ms(3);

		a=0;
		if(READ_SDA)
		{
			a=1;
		}
		else
		{
			a=0;
		}

		//resultByte = resultByte | a;
		resultByte = (resultByte << 1) | a;

		IIC_SCL = 0;
		delay_ms(3);
	}

	SDA_IN();
	delay_ms(10);

	return   resultByte;
}


void  set_AHT10sendOutData(void)
{
	/* --------------------------
	 * 0xFA 0x06 0x0A temperature(2 Bytes) humility(2Bytes) short Address(2 Bytes)
	 * And Check (1 byte)
	 * -------------------------*/
	AHT10sendOutData[3] = AHT10_OutData[0];
	AHT10sendOutData[4] = AHT10_OutData[1];
	AHT10sendOutData[5] = AHT10_OutData[2];
	AHT10sendOutData[6] = AHT10_OutData[3];
}


void  I2C_Start(void)
{
	SDA_OUT();
	IIC_SCL = 1;
	delay_ms(4);

	IIC_SDA = 1;
	delay_ms(4);
	IIC_SDA = 0;
	delay_ms(4);

	IIC_SCL = 0;
	delay_ms(4);
}



void  I2C_Stop(void)
{
	SDA_OUT();
	IIC_SDA = 0;
	delay_ms(4);

	IIC_SCL = 1;
	delay_ms(4);

	IIC_SDA = 1;
	delay_ms(4);
}

bsp_can.c

#include "./can/bsp_can.h"
#include "./delay/delay.h"


/*
 * 函数名:CAN_GPIO_Config
 * 描述  :CAN的GPIO 配置
 * 输入  :无
 * 输出  : 无
 * 调用  :内部调用
 */
static void CAN_GPIO_Config(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;   	

  /* Enable GPIO clock */
  RCC_APB2PeriphClockCmd(CAN_TX_GPIO_CLK|CAN_RX_GPIO_CLK, ENABLE);
	//重映射引脚
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);

	 /* Configure CAN TX pins */
  GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		         // 复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);
	
	/* Configure CAN RX  pins */
  GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	             // 上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
}

/*
 * 函数名:CAN_NVIC_Config
 * 描述  :CAN的NVIC 配置,第1优先级组,0,0优先级
 * 输入  :无
 * 输出  : 无
 * 调用  :内部调用
 */
static void CAN_NVIC_Config(void)
{
   	NVIC_InitTypeDef NVIC_InitStructure;
		/* Configure one bit for preemption priority */
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	 	/*中断设置*/
		NVIC_InitStructure.NVIC_IRQChannel = CAN_RX_IRQ;	   //CAN1 RX0中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;		   //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;			   //子优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*
 * 函数名:CAN_Mode_Config
 * 描述  :CAN的模式 配置
 * 输入  :无
 * 输出  : 无
 * 调用  :内部调用
 */
static void CAN_Mode_Config(void)
{
	CAN_InitTypeDef        CAN_InitStructure;
	/************************CAN通信参数设置**********************************/
	/* Enable CAN clock */
  RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);

	/*CAN寄存器初始化*/
	CAN_DeInit(CANx);
	CAN_StructInit(&CAN_InitStructure);

	/*CAN单元初始化*/
	CAN_InitStructure.CAN_TTCM=DISABLE;			   //MCR-TTCM  关闭时间触发通信模式使能
	CAN_InitStructure.CAN_ABOM=ENABLE;			   //MCR-ABOM  自动离线管理 
	CAN_InitStructure.CAN_AWUM=ENABLE;			   //MCR-AWUM  使用自动唤醒模式
	CAN_InitStructure.CAN_NART=DISABLE;			   //MCR-NART  禁止报文自动重传	  DISABLE-自动重传
	CAN_InitStructure.CAN_RFLM=DISABLE;			   //MCR-RFLM  接收FIFO 锁定模式  DISABLE-溢出时新报文会覆盖原有报文  
	CAN_InitStructure.CAN_TXFP=DISABLE;			   //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 
	CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  //正常工作模式
	
	CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; 
  CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; 
  
	CAN_InitStructure.CAN_BS2=CAN_BS2_2tq; 
  CAN_InitStructure.CAN_Prescaler=60; 

	//CAN_InitStructure.CAN_SJW=CAN_SJW_2tq;		   //BTR-SJW 重新同步跳跃宽度 2个时间单元
	 
	/* ss=1 bs1=5 bs2=3 位时间宽度为(1+5+3) 波特率即为时钟周期tq*(1+3+5)  */
	//CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;		   //BTR-TS1 时间段1 占用了5个时间单元
	//CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;		   //BTR-TS1 时间段2 占用了3个时间单元	
	
	/* CAN Baudrate = 1 MBps (1MBps已为stm32的CAN最高速率) (CAN 时钟频率为 APB1 = 36 MHz) */
	//CAN_InitStructure.CAN_Prescaler =4;		   ////BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+5+3)/4=1 Mbps
	CAN_Init(CANx, &CAN_InitStructure);
}

/*
 * 函数名:CAN_Filter_Config
 * 描述  :CAN的过滤器 配置
 * 输入  :无
 * 输出  : 无
 * 调用  :内部调用
 */
static void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;

	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;	//工作在掩码模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;	//筛选器位宽为单个32位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */

	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;		//要筛选的ID高位 
	CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要筛选的ID低位 
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF;			//筛选器高16位每位必须匹配
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF;			//0xFFFF筛选器低16位每位必须匹配
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}


/*
 * 函数名:CAN_Config
 * 描述  :完整配置CAN的功能
 * 输入  :无
 * 输出  : 无
 * 调用  :外部调用
 */
void CAN_Config(void)
{
  CAN_GPIO_Config();
  CAN_NVIC_Config();
  CAN_Mode_Config();
  CAN_Filter_Config();   
}


/**
  * @brief  初始化 Rx Message数据结构体
  * @param  RxMessage: 指向要初始化的数据结构体
  * @retval None
  */
void Init_RxMes(CanRxMsg *RxMessage)
{
  uint8_t ubCounter = 0;

	/*把接收结构体清零*/
  RxMessage->StdId = 0x00;
  RxMessage->ExtId = 0x00;
  RxMessage->IDE = CAN_ID_STD;
  RxMessage->DLC = 0;
  RxMessage->FMI = 0;
  for (ubCounter = 0; ubCounter < 8; ubCounter++)
  {
    RxMessage->Data[ubCounter] = 0x00;
  }
}


/*
 * 函数名:CAN_SetMsg
 * 描述  :CAN通信报文内容设置,设置一个数据内容为0-7的数据包
 * 输入  :发送报文结构体
 * 输出  : 无
 * 调用  :外部调用
 */	 
void CAN_SetMsg(CanTxMsg *TxMessage,double T1,double H1)
{	  
	

  //TxMessage.StdId=0x00;						 
  TxMessage->ExtId=0x1314;					 //使用的扩展ID
  TxMessage->IDE=CAN_ID_EXT;					 //扩展模式
  TxMessage->RTR=CAN_RTR_DATA;				 //发送的是数据
  TxMessage->DLC=2;							 //数据长度为8字节
	
	TxMessage->Data[0] = T1;
	TxMessage->Data[1] = H1;

}
/**************************END OF FILE************************************/

main.c

 /**
  ******************************************************************************
  *     main.c
  *    CAN通讯实验温湿度端
  ******************************************************************************
  */ 
#include "stm32f10x.h"
#include "./usart/bsp_usart.h" 
#include "./can/bsp_can.h"
#include "./oled/oled.h"  
#include "./delay/delay.h" 
#include "./bsp_i2c/bsp_i2c.h"

//函数声明
void GPIO_Configuration(void);

uint8_t t;
uint8_t len;
uint16_t times=0;
extern uint32_t T1;
extern uint32_t H1;

__IO uint32_t flag = 0;		 //用于标志是否接收到数据,在中断函数中赋值
CanTxMsg TxMessage;			     //发送缓冲区
CanRxMsg RxMessage;				 //接收缓冲区
 

/*
 * 函数名:main
 * 描述  :主函数
 * 输入  :无
 * 输出  :无
 */
int main(void)
{ 	
	float t=0;
	double T;
	double H;
	vu8 key=0;//定义键值	
	
	double ShowBuff[8]={0};
	double ShowBuff1[8]={0};
	
	GPIO_Configuration();//pc13灯 初始化
	
	delay_ms(500);
	
	
	/* 配置串口为:115200 8-N-1 */
	USART_Config(); //不可去掉否则不能正常工作
	
	 IIC_Init();
	 CAN_Config();   
	

   PCout(13)=0;
   
	while(1)
	{
		read_AHT10_once();
		
	    T=T1/10.0;
        H=H1/10.0;
		
		ShowBuff[0] = T + '0';
		ShowBuff1[0] = H + '0';
		
		CAN_SetMsg(&TxMessage,ShowBuff[0],ShowBuff1[0]);
		CAN_Transmit(CANx, &TxMessage);
		
		delay_ms(3000);
		
	}	
	}

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC , ENABLE); 						 
//=============================================================================
//LED -> PC13
//=============================================================================			 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

显示屏端

can.c和bsp_can.c是一样的就不复述了

oled.c

你需要根据你的显示屏自己设置,问你的商家要oled代码就可以了,道理是一样的,当然用法也是

mian.c

 /**
  ******************************************************************************
  *    main.c
  *   CAN通讯实验显示屏端
  ******************************************************************************
  */ 
#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "GPIOLIKE51.h"
#include "./can/bsp_can.h"
#include "./oled/oled.h"  
#include "./delay/delay.h" 

//函数声明
void GPIO_Configuration(void);

uint8_t t;
uint8_t len;
uint16_t times=0;

__IO uint32_t flag = 0;         //用于标志是否接收到数据,在中断函数中赋值
CanTxMsg TxMessage;                 //发送缓冲区
CanRxMsg RxMessage;                 //接收缓冲区
 

/*
 * 函数名:main
 * 描述  :主函数
 * 输入  :无
 * 输出  :无
 */
int main(void)
{     
    
    char ShowBuff[8]={0};
  
  
    OLED_Init();//初始化OLED
    OLED_Clear();//清屏 
    
    GPIO_Configuration();//pc13灯 初始化
    
    delay_ms(500);
    
    
    /* 配置串口为:115200 8-N-1 */
    USART_Config(); //不可去掉否则不能正常工作
    
    IIC_Init();
    
     CAN_Config();   

   PCout(13)=0;
    
     
     
   
    while(1)
    {
        //OLED_Clear();    
        ShowBuff[0] = RxMessage.Data[0];
        ShowBuff[1] = RxMessage.Data[1];
        
        OLED_ShowCHinese(24,0,0);
        OLED_ShowCHinese(45,0,1);
        OLED_ShowCHinese(65,0,2);
        
        OLED_ShowString(0,3,"Temp");
        OLED_ShowNum(35,3,ShowBuff[0]+'2',4);
        OLED_ShowString(75,3,"*C");
        

        OLED_ShowString(0,5,"Humi");
        OLED_ShowNum(35,5,ShowBuff[1]+'2',4);
        OLED_ShowString(75,5,"%");
        delay_ms(500);
    
        
    }    
    
    }

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC , ENABLE);                          
//=============================================================================
//LED -> PC13
//=============================================================================             
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

总结

其实也真的没有什么的,需要源码的话可以给我写邮件17630925326@163.com,当然留言也可以

成品是这样的

成品