IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F103C8T6读取74HC165移位寄存器CAN发送接收到的键值 -> 正文阅读

[嵌入式]STM32F103C8T6读取74HC165移位寄存器CAN发送接收到的键值

一. 74hc165.h

#ifndef _74HC165_H
#define _74HC165_H

#include "sys.h"
#include "delay.h"
#include "rs485.h" 
#include "can.h" 
/**
*74HC165
 *@param	
 *@careful	 
 *@return	 						
 */	 
#define HC165_LD  	PAout(4)  //PL 并行数据输入使能,低电平有效  (PL)
#define HC165_CLK   PAout(5)	//CP 时钟,上升沿触发
#define HC165_QH    PAin(6)		//QH 串行数据输出 (OUT) 
void _74hc165_init(void); 
void _74hc165_read_3byte(u8 date[3]);
void s1u1_24(void);
   
#endif 

二. 74hc165.c

#include "74hc165.h" 

//初始化74hc165
void _74hc165_init(void)
{
	RCC->APB2ENR|=1<<2;    //使能PORTA时钟
	GPIOA->CRL&=0XF000FFFF;//A4,A5通用开漏输出2MHz; A6设置成浮空输入    
	GPIOA->CRL|=0X08880000;  //0XA8AA0000
	
	HC165_LD = 1; //PL拉高,不读取按键状态
	HC165_CLK = 1; //时钟拉高,便于产生上升沿
} 
//读取3个74hc165数据
u8 i;
int temp; 
void _74hc165_read_3byte(u8 date[3])
{
	HC165_LD = 0; //PL拉低,读取按键状态 
	delay_us(10); 	
	HC165_LD = 1; //PL拉高,停止按键读取    
	for(i = 0; i < 24; i++) 
	{
		temp <<= 1;
		HC165_CLK = 0;	//拉低时钟引脚	
		delay_us(10);   //延时10us
		if(HC165_QH == 1)//读取数据输出引脚的电平,如果为高则置1
			temp |= 0x01;  
		HC165_CLK = 1;	//拉高时钟引脚 
	}    
	//将24位数据分离为3个8位数据
	date[0] = (u8)(temp & 0x00ff);//第3级74HC165的数据
	date[1] = (u8)((temp >> 8) & 0x00ff);//第2级74HC165的数据
	date[2] = (u8)((temp >> 16) & 0x00ff);//第1级74HC165的数据
	temp=0;
	delay_ms(100);
}

三. main.c

#include "sys.h"
#include "usart.h"	
#include "delay.h"	  
#include "can.h"    
#include "74hc165.h"  
/**
*main函数
 *@param	
 *@careful	 
 *@return	 						
 */	 
int main(void)
{	
	u8 key2state[3]={0xFF,0xFF,0xFF};
	Stm32_Clock_Init(9);  //系统时钟设置
	delay_init(72);	      //延时初始化 
	_74hc165_init();	  //74HC165初始化 1-24
	CAN_Mode_Init(1,8,9,4,0);	//CAN初始化,波特率500Kbps   0:普通模式
	printf("RUN! \r\n");   
  	while(1)
  	{   
		delay_ms(200); 
		_74hc165_read_3byte(key2state);//读取3级74HC165的数据,即24个按键的状态
		CAN_Send_Msg_Hex(key2state,3);//发送读到的数据 
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四. can.h

#ifndef __CAN_H
#define __CAN_H	 
#include "sys.h"	    

#define CAN_ENABLE		PAout(15)	//1:待机

//CAN接收RX0中断使能
#define CAN_RX0_INT_ENABLE	1		//0,不使能;1,使能.	

//500rpm:  01 F4
//1000rpm: 03 E8
 
extern u16 rpm; //速度rpm
extern int time; //记录时间					    
										 							 				    
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);//CAN初始化
u8 CAN_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat);		//发送数据
u8 CAN_Msg_Pend(u8 fifox);								//查询邮箱报文
void CAN_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat);//接收数据
u8 CAN_Tx_Staus(u8 mbox);  								//返回发送状态
u8 CAN_Send_Msg(u8* msg,u8 len);						//发送数据
u8 CAN_Send_Msg_Hex(u8* msg,u8 len);					//发送数据
u8 CAN_Receive_Msg(u8 *buf);	//接收数据

u8 CAN_Tx_Msg_u16(u32 id,u8 ide,u8 rtr,u8 len,u16 *dat);
u8 CAN_Send_Msg_Hex_u16(u16* msg,u8 len);


#endif
 

五. can.c

#include "can.h"
#include "usart.h"
#include "delay.h"
/**
 *CAN初始化
 *@param	tsjw:重新同步跳跃时间单元.范围:1~3;
 *			tbs2:时间段2的时间单元.范围:1~8;
 *			tbs1:时间段1的时间单元.范围:1~16;
 *			brp :波特率分频器.范围:1~1024;
 *			mode:0,普通模式;1,回环模式;
 *@careful	 
 *@return	 						
 */	
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
	u16 i=0;
 	if(tsjw==0||tbs2==0||tbs1==0||brp==0)return 1;
	tsjw-=1;//先减去1.再用于设置
	tbs2-=1;
	tbs1-=1;
	brp-=1;
	//1,配置相关引脚的复用功能,使能CAN时钟。
	RCC->APB2ENR|=1<<2;    	//使能PORTA时钟	 
	RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;  //使能AFIO时钟
	AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE; //关闭JTAG 释放出PB3,PB4,PA15  
	GPIOA->CRH&=0X0FFFFFFF; //A15
	GPIOA->CRH|=0X80000000;	//IO状态设置   
	GPIOA->ODR &=0x7FFF;    //下拉 
  //GPIOA->ODR|=0<<15;     //PA15 输出低 	
	
	GPIOA->CRH&=0XFFF00FFF; //PA11 RX,PA12 TX
	GPIOA->CRH|=0X000B8000;	//IO状态设置    	 
  GPIOA->ODR|=3<<11;
					    
	RCC->APB1ENR|=1<<25;	//使能CAN时钟 CAN使用的是APB1的时钟(max:36M)
	CAN1->MCR=0x0000;		//退出睡眠模式(同时设置所有位为0)
	CAN1->MCR|=1<<0;		//请求CAN进入初始化模式
	while((CAN1->MSR&1<<0)==0)
	{
		i++;
		if(i>100)return 2;	//进入初始化模式失败
	}
	//2,设置CAN工作模式及波特率等
	CAN1->MCR|=0<<7;		//非时间触发通信模式
	CAN1->MCR|=0<<6;		//软件自动离线管理
	CAN1->MCR|=0<<5;		//睡眠模式通过软件唤醒(清除CAN1->MCR的SLEEP位)
	CAN1->MCR|=1<<4;		//禁止报文自动传送
	CAN1->MCR|=0<<3;		//报文不锁定,新的覆盖旧的
	CAN1->MCR|=0<<2;		//优先级由报文标识符决定
	CAN1->BTR=0x00000000;	//清除原来的设置.
	CAN1->BTR|=mode<<30;	//模式设置 0,普通模式;1,回环模式;
	CAN1->BTR|=tsjw<<24; 	//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
	CAN1->BTR|=tbs2<<20; 	//Tbs2=tbs2+1个时间单位
	CAN1->BTR|=tbs1<<16;	//Tbs1=tbs1+1个时间单位
	CAN1->BTR|=brp<<0;  	//分频系数(Fdiv)为brp+1
							//波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv)
	CAN1->MCR&=~(1<<0);		//请求CAN退出初始化模式
	while((CAN1->MSR&1<<0)==1)
	{
		i++;
		if(i>0XFFF0)return 3;//退出初始化模式失败
	}
	//3,设置过滤器
	CAN1->FMR|=1<<0;		//过滤器组工作在初始化模式
	CAN1->FA1R&=~(1<<0);	//过滤器0不激活
	CAN1->FS1R|=1<<0; 		//过滤器位宽为32位.
	CAN1->FM1R|=0<<0;		//过滤器0工作在标识符屏蔽位模式
	CAN1->FFA1R|=0<<0;		//过滤器0关联到FIFO0
	CAN1->sFilterRegister[0].FR1=0X00000000;//32位ID
	CAN1->sFilterRegister[0].FR2=0X00000000;//32位MASK
	CAN1->FA1R|=1<<0;		//激活过滤器0
	CAN1->FMR&=0<<0;		//过滤器组进入正常模式

#if CAN_RX0_INT_ENABLE
 	//使用中断接收
	CAN1->IER|=1<<1;		//FIFO0消息挂号中断允许.	    
	MY_NVIC_Init(0,0,USB_LP_CAN1_RX0_IRQn,4);//组4
#endif
	return 0;
}   


/**
 * 
 *@param	id:标准ID(11位)/扩展ID(11位+18位)	
 *				ide:0,标准帧;1,扩展帧
 *				rtr:0,数据帧;1,远程帧
 *				len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
 *				dat:数据指针. 
 *@careful	 
 *@return 返回值:0~3,邮箱编号.0XFF,无有效邮箱.						
 */	 
u8 CAN_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat)
{	   
	u8 mbox;	  
	if(CAN1->TSR&(1<<26))mbox=0;		//邮箱0为空
	else if(CAN1->TSR&(1<<27))mbox=1;	//邮箱1为空
	else if(CAN1->TSR&(1<<28))mbox=2;	//邮箱2为空
	else return 0XFF;					//无空邮箱,无法发送 
	CAN1->sTxMailBox[mbox].TIR=0;		//清除之前的设置
	if(ide==0)	//标准帧
	{
		id&=0x7ff;//取低11位stdid
		id<<=21;		  
	}else		//扩展帧
	{
		id&=0X1FFFFFFF;//取低32位extid
		id<<=3;									   
	}
	CAN1->sTxMailBox[mbox].TIR|=id;		 
	CAN1->sTxMailBox[mbox].TIR|=ide<<2;	  
	CAN1->sTxMailBox[mbox].TIR|=rtr<<1;
	len&=0X0F;//得到低四位
	CAN1->sTxMailBox[mbox].TDTR&=~(0X0000000F);
	CAN1->sTxMailBox[mbox].TDTR|=len;	//设置DLC.
	//待发送数据存入邮箱.
	CAN1->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
								((u32)dat[6]<<16)|
 								((u32)dat[5]<<8)|
								((u32)dat[4]));
	CAN1->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
								((u32)dat[2]<<16)|
 								((u32)dat[1]<<8)|
								((u32)dat[0]));
	CAN1->sTxMailBox[mbox].TIR|=1<<0; 	//请求发送邮箱数据
	return mbox;
}


/**
 * 获得发送状态.
 *@param	mbox:邮箱编号;
 *				返回值:发送状态. 0,挂起;0X05,发送失败;0X07,发送成功.
 *@careful	tq=(brp)*tpclk1 注意tsjw,tbs2,tbs1,brp不能设为0,否则会乱.
			波特率=Fpclk1/((tbs1+tbs2+1)*brp;
 *@return	0,初始化OK; 其他,初始化失败;							
 */	  
u8 CAN_Tx_Staus(u8 mbox)
{	
	u8 sta=0;					    
	switch (mbox)
	{
		case 0: 
			sta |= CAN1->TSR&(1<<0);		//RQCP0
			sta |= CAN1->TSR&(1<<1);		//TXOK0
			sta |=((CAN1->TSR&(1<<26))>>24);//TME0
			break;
		case 1: 
			sta |= CAN1->TSR&(1<<8)>>8;		//RQCP1
			sta |= CAN1->TSR&(1<<9)>>8;		//TXOK1
			sta |=((CAN1->TSR&(1<<27))>>25);//TME1	   
			break;
		case 2: 
			sta |= CAN1->TSR&(1<<16)>>16;	//RQCP2
			sta |= CAN1->TSR&(1<<17)>>16;	//TXOK2
			sta |=((CAN1->TSR&(1<<28))>>26);//TME2
			break;
		default:
			sta=0X05;//邮箱号不对,肯定失败.
		break;
	}
	return sta;
} 
//得到在FIFO0/FIFO1中接收到的报文个数.
//fifox:0/1.FIFO编号;
//返回值:FIFO0/FIFO1中的报文个数.
u8 CAN_Msg_Pend(u8 fifox)
{
	if(fifox==0)return CAN1->RF0R&0x03; 
	else if(fifox==1)return CAN1->RF1R&0x03; 
	else return 0;
}

/**
 * 接收数据
 *@param	fifox:邮箱号
 *				id:标准ID(11位)/扩展ID(11位+18位)	 
 *				ide:0,标准帧;1,
 *				rtr:0,数据帧;1,远程帧
 *				len:接收到的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
 *				dat:数据缓存区
 *@careful 
 *@return	 						
 */	   
void CAN_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat)
{	   
	*ide=CAN1->sFIFOMailBox[fifox].RIR&0x04;	//得到标识符选择位的值  
 	if(*ide==0)//标准标识符
	{
		*id=CAN1->sFIFOMailBox[fifox].RIR>>21;
	}else	   //扩展标识符
	{
		*id=CAN1->sFIFOMailBox[fifox].RIR>>3;
	}
	*rtr=CAN1->sFIFOMailBox[fifox].RIR&0x02;	//得到远程发送请求值.
	*len=CAN1->sFIFOMailBox[fifox].RDTR&0x0F;	//得到DLC
 	//*fmi=(CAN1->sFIFOMailBox[FIFONumber].RDTR>>8)&0xFF;//得到FMI
	//接收数据
	dat[0]=CAN1->sFIFOMailBox[fifox].RDLR&0XFF;
	dat[1]=(CAN1->sFIFOMailBox[fifox].RDLR>>8)&0XFF;
	dat[2]=(CAN1->sFIFOMailBox[fifox].RDLR>>16)&0XFF;
	dat[3]=(CAN1->sFIFOMailBox[fifox].RDLR>>24)&0XFF;    
	dat[4]=CAN1->sFIFOMailBox[fifox].RDHR&0XFF;
	dat[5]=(CAN1->sFIFOMailBox[fifox].RDHR>>8)&0XFF;
	dat[6]=(CAN1->sFIFOMailBox[fifox].RDHR>>16)&0XFF;
	dat[7]=(CAN1->sFIFOMailBox[fifox].RDHR>>24)&0XFF;    
  	if(fifox==0)CAN1->RF0R|=0X20;//释放FIFO0邮箱
	else if(fifox==1)CAN1->RF1R|=0X20;//释放FIFO1邮箱	 
}

#if CAN_RX0_INT_ENABLE	//使能RX0中断 
/**
 * 中断服务函数
 *@param	 
 *@careful 
 *@return	 						
 */	
//void USB_LP_CAN1_RX0_IRQHandler(void)
//{
//	u8 rxbuf[8];
//	u32 id;
//	u8 ide,rtr,len;
// 	CAN_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);
//  printf("id:%d\r\n",id);
//  printf("ide:%d\r\n",ide);
//  printf("rtr:%d\r\n",rtr);
//	printf("rxbuf:%d %d %d %d %d %d %d %d\r\n",rxbuf[0],rxbuf[1],rxbuf[2],rxbuf[3],rxbuf[4],rxbuf[5],rxbuf[6],rxbuf[7]);
//	CAN_Send_Msg(rxbuf,8);//接收返回 
//}
u16 rpm=2990; //速度rpm
int timeUp=0; //记录上升沿时间 
int timeDn=0; //记录下降沿时间 
u8 TestK=0;

/**
 * 中断服务函数-提取转速数据帧
 *@param	 
 *@careful 
 *@return	 						
 */	    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	u8 rxbuf[8];
	u32 id;
	u8 ide,rtr,len;     
 
	int valUp = 0; //用于存放合并后的16进制数
	char *pBufUp = (char*)&valUp;  //数据低四位 
	int valDn = 0; //用于存放合并后的16进制数
	char *pBufDn = (char*)&valDn;  //数据低四位 
	CAN_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf); //读取一组数据 
	
	//上升沿 - 合并数据位的16进制并输出10进制
	pBufUp[0] = rxbuf[5];
	pBufUp[1] = rxbuf[4];
	
	//下降沿 - 合并数据位的16进制并输出10进制 
	pBufDn[0] = rxbuf[5];
	pBufDn[1] = rxbuf[4];
	 
	//if(KEY0==1)		//按键KEY0
	//{	 
	//	//上升沿
	//	if(valUp==0)timeUp=0; 		//转速为0时间标志位也为0
	//	if(valUp>=1&&valUp<rpm-1)	//转速提升时:在1和设定转速之间
	//	{ 
	//		delay_ms(1);
	//		timeUp+=1; //每1ms记一次数 
	//		if((valUp>rpm*0.8+70)&&(valUp<rpm*0.8+230)) printf("0.8++++++++++++++++++++++++++加速到百分之80 :"); 
	//		if(valUp>=rpm*0.997) printf("1+++++++++++++++++++++++++++++加速到百分之100:"); 
	//		printf("速度    :%drpm   ",valUp); 
	//		printf("启动用时:%dms\r\n",timeUp); 
	//	}
	//	//if((valUp==rpm-1)&&(valUp!=valUp-1)) //转速达到设定值减1
	//	//{ 
	//	//	printf("速度    :%drpm   ",valUp+1); 
	//	//	printf("启动用时:%dms\r\n",timeUp);  
	//	//}
	//	if(valUp==rpm){}; //达到指定转速
	//}
	//if(KEY0==0)		//按键KEY0
	//{	 
	//	//下降沿 
	//	if((valDn>rpm-25)&&(valDn<rpm+25))timeDn=0; //转速为指定转速
	//	if((valDn<rpm-1)&&(valDn>=2)) //转速减速时:在1和设定转速之间
	//	{ 
	//		delay_ms(1);
	//		timeDn+=1; //每1ms记一次数
	//		if((valDn>rpm*0.2+50)&&(valDn<rpm*0.2+230)) printf("0.2--------------------------减速到百分之20 :");
	//		if(valDn<=2) printf("0----------------------------减速到接近于0  :");  
	//		printf("速度    :%drpm   ",valDn); 
	//		printf("停止用时:%dms\r\n",timeDn);  
	//	}
	//	//if(valDn==1) //转速降到1 
	//	//{ 
	//	//	printf("速度    :%drpm   ",valDn+1); 
	//	//	printf("停止用时:%dms\r\n",timeDn);  
	//	//}
	//	if(valDn<=5){};
	//}
	CAN_Send_Msg(rxbuf,8);//接收返回 
}
#endif

/**
 * 
 *@param	can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
 *				len:数据长度(最大为8)	
 *				msg:数据指针,最大为8个字节.
 *@careful 
 *@return 返回值:0,成功; 其他,失败;
 */	   
u8 CAN_Send_Msg(u8* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;	  	 						       
    mbox=CAN_Tx_Msg(0X12,0,0,len,msg);
	while((CAN_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++;//等待发送结束
	if(i>=0XFFF)return 1;							//发送失败?
	return 0;										//发送成功;
}


/**
 * 
 *@param	can口接收数据查询
 *				buf:数据缓存区;	 
 *@careful 
 *@return	返回值:0,无数据被收到; 其他,接收的数据长度;		
 */	  
u8 CAN_Receive_Msg(u8 *buf)
{		   		   
	u32 id;
	u8 ide,rtr,len; 
	if(CAN_Msg_Pend(0)==0)return 0;			//没有接收到数据,直接退出 	 
  	CAN_Rx_Msg(0,&id,&ide,&rtr,&len,buf); 	//读取数据
    if(id!=0x12||ide!=0||rtr!=0)len=0;		//接收错误	   
	return len;	
}



/**
 * 
 *@param	id:标准ID(11位)/扩展ID(11位+18位)	 
 *				ide:0,标准帧;1,扩展帧  
 *				rtr:0,数据帧;1,远程帧
 *				len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
 *				*dat:数据指针.
 *@careful 
 *@return	返回值:0~3,邮箱编号.0XFF,无有效邮箱.			
 */	  
u8 CAN_Tx_Msg_u8(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat)
{	   
	u8 mbox;	  
	if(CAN1->TSR&(1<<26))mbox=0;		//邮箱0为空
	else if(CAN1->TSR&(1<<27))mbox=1;	//邮箱1为空
	else if(CAN1->TSR&(1<<28))mbox=2;	//邮箱2为空
	else return 0XFF;					//无空邮箱,无法发送 
	CAN1->sTxMailBox[mbox].TIR=0;		//清除之前的设置
	if(ide==0)	//标准帧
	{
		id&=0x7ff;//取低11位stdid
		id<<=21;		  
	}else		//扩展帧
	{
		id&=0X1FFFFFFF;//取低32位extid
		id<<=3;									   
	}
	CAN1->sTxMailBox[mbox].TIR|=id;		 
	CAN1->sTxMailBox[mbox].TIR|=ide<<2;	  
	CAN1->sTxMailBox[mbox].TIR|=rtr<<1;
	len&=0X0F;//得到低四位
	CAN1->sTxMailBox[mbox].TDTR&=~(0X0000000F);
	CAN1->sTxMailBox[mbox].TDTR|=len;	//设置DLC.
	//待发送数据存入邮箱.
	CAN1->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
								((u32)dat[6]<<16)|
 								((u32)dat[5]<<8)|
								((u32)dat[4]));
	CAN1->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
								((u32)dat[2]<<16)|
 								((u32)dat[1]<<8)|
								((u32)dat[0]));
	CAN1->sTxMailBox[mbox].TIR|=1<<0; 	//请求发送邮箱数据
	return mbox;
}
/**
 * can发送一组数据-hex(固定格式:ID为0X12,标准帧,数据帧)	
 *@param	len:数据长度(最大为8)	
 *				msg:数据指针,最大为8个字节.  
 *@careful 
 *@return	//返回值:0,成功; 其他,失败; 						
 */	  
u8 CAN_Send_Msg_Hex(u8* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;	  	 						       
    mbox=CAN_Tx_Msg_u8(0X101,0,0,len,msg);
	while((CAN_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++;//等待发送结束
	if(i>=0XFFF)return 1;							//发送失败?
	return 0;										//发送成功;
}


/**
 * 
 *@param	id:标准ID(11位)/扩展ID(11位+18位)	 
 *				ide:0,标准帧;1,扩展帧  
 *				rtr:0,数据帧;1,远程帧
 *				len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
 *				*dat:数据指针.
 *@careful 
 *@return	返回值:0~3,邮箱编号.0XFF,无有效邮箱.			
 */	  
u8 CAN_Tx_Msg_u16(u32 id,u8 ide,u8 rtr,u8 len,u16 *dat)
{	   
	u8 mbox;	  
	if(CAN1->TSR&(1<<26))mbox=0;		//邮箱0为空
	else if(CAN1->TSR&(1<<27))mbox=1;	//邮箱1为空
	else if(CAN1->TSR&(1<<28))mbox=2;	//邮箱2为空
	else return 0XFF;					//无空邮箱,无法发送 
	CAN1->sTxMailBox[mbox].TIR=0;		//清除之前的设置
	if(ide==0)	//标准帧
	{
		id&=0x7ff;//取低11位stdid
		id<<=21;		  
	}else		//扩展帧
	{
		id&=0X1FFFFFFF;//取低32位extid
		id<<=3;									   
	}
	CAN1->sTxMailBox[mbox].TIR|=id;		 
	CAN1->sTxMailBox[mbox].TIR|=ide<<2;	  
	CAN1->sTxMailBox[mbox].TIR|=rtr<<1;
	len&=0X0F;//得到低四位
	CAN1->sTxMailBox[mbox].TDTR&=~(0X0000000F);
	CAN1->sTxMailBox[mbox].TDTR|=len;	//设置DLC.
	//待发送数据存入邮箱.
	CAN1->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
								((u32)dat[6]<<16)|
 								((u32)dat[5]<<8)|
								((u32)dat[4]));
	CAN1->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
								((u32)dat[2]<<16)|
 								((u32)dat[1]<<8)|
								((u32)dat[0]));
	CAN1->sTxMailBox[mbox].TIR|=1<<0; 	//请求发送邮箱数据
	return mbox;
}
/**
 * can发送一组数据-hex(固定格式:ID为0X12,标准帧,数据帧)	
 *@param	len:数据长度(最大为8)	
 *				msg:数据指针,最大为8个字节.  
 *@careful 
 *@return	//返回值:0,成功; 其他,失败; 						
 */	  
u8 CAN_Send_Msg_Hex_u16(u16* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;	  	 						       
    mbox=CAN_Tx_Msg_u16(0X101,0,0,len,msg);
	while((CAN_Tx_Staus(mbox)!=0X07)&&(i<0XFFF))i++;//等待发送结束
	if(i>=0XFFF)return 1;							//发送失败?
	return 0;										//发送成功;
}
  
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:52:42  更:2022-04-22 18:56:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:35:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码