使用STM32HAL库实现RX8010SJ驱动

前言:

        RX8010SJ为一款硬件RTC芯片,通过IIC驱动。IIC建议速率100K~400K,使用STM32的HAL库函数实现IIC驱动。工程可以使用STM32CubeMX快速构建。

一.平台说明

        MCU为STM32H743,使用HAL库函数,编译器使用KEIL5

二.具体驱动实现

RX8010SJ驱动,包括初始化、设备读写函数,BCD、BIN格式转换,周计算及解析函数。

1.dev_rx8010sj.c

#include "dev_rx8010sj.h"
/*---------------------------------------------------------------------------------------
函数名:    Dev_RX8010SJ_Init()
函数功能:  RX8010SJ设备初始化
参数:  
返回值:
备注:
----------------------------------------------------------------------------------------*/
void Dev_RX8010SJ_Init(void)
{
    BSP_IIC_INIT();//IIC总线初始化
}
/*---------------------------------------------------------------------------------------
函数名:    RTC_BinToBcd()
函数功能:  十进制转BCD码
参数:  BinValue:十进制输入值
返回值:cacheBuf:BCD码转换值
备注:
----------------------------------------------------------------------------------------*/
static uint8_t RTC_BinToBcd(uint8_t BinValue)
{
	uint8_t cacheBuf = 0;
	
	while(BinValue >= 10)
	{
		BinValue -= 10;
		cacheBuf += 1;
	}
	
	cacheBuf = (cacheBuf<<4) + BinValue;
	
	return (cacheBuf);
}
/*---------------------------------------------------------------------------------------
函数名:    RTC_BcdToBin()
函数功能:  BCD转十进制
参数:  BCDValue:BCD输入值
返回值:cacheBuf:十进制转换值,xRegister:有效位
备注:
----------------------------------------------------------------------------------------*/
static uint8_t RTC_BcdToBin(uint8_t BCDValue,uint8_t xRegister)
{
	uint8_t cacheBuf = 0;
		
	cacheBuf = ( BCDValue & (xRegister&0xF0) ) >> 4;
	cacheBuf = cacheBuf*10 + (BCDValue & (xRegister&0x0F)); 
	
	return (cacheBuf);
}
/*---------------------------------------------------------------------------------------
函数名:    RTC_Cal_Week()
函数功能:  根据年月日计算周
参数:  year:年 month:月 day:日
返回值:周序号(0~6)
备注:
----------------------------------------------------------------------------------------*/
uint8_t RTC_Cal_Week(uint16_t year,uint8_t month,uint8_t day)
{     
	uint8_t weekday; 
	if(month==1||month==2) 
	{
		month+=12;
		year--;
	}
	weekday=(day+2*month+3*(month+1)/5+year+year/4-year/100+year/400)%7+1;
	if(weekday==7) //0代表周日,1~6代表周一至周六
	{
		weekday=0;
	}
	return weekday;
}

/*---------------------------------------------------------------------------------------
函数名:    RTC_Get_Week()
函数功能:  解析RX8010返回周
参数:  Weekday:RX8010SJ周寄存器值
返回值:周序号(0~6)
备注:
----------------------------------------------------------------------------------------*/
uint8_t RTC_Get_Week(uint8_t Weekday)
{     
	uint8_t i;
	for(i=0;i<7;i++)
	{
		if(Weekday&(0x01<<i))
		{
			return i;
		}
	}
    //周寄存器为非法值
	return 0xff;
}
/*---------------------------------------------------------------------------------------
函数名:    Write_To_RX8010SJ()
函数功能:  写实时时钟
参数:set_RX8010SJ_time,时间参数结构体,周需要进行二次计算
返回值:无
备注:
----------------------------------------------------------------------------------------*/
void Write_To_RX8010SJ(RX8010SJ_Info* set_RX8010SJ_time)
{	
	uint8_t temp_u8;
	RX8010SJ_Info Time_set;
	/*修改控制寄存器允许写时间*/
	temp_u8 = 0x40;
	BSP_IIC_Send_Data(RX8010SJ_IIC_W_ADDR,RX8010_ADDR_CTRL_REG,(uint8_t *)&temp_u8,1);
	/*时间转换为BCD码*/
	Time_set.time.Second = RTC_BinToBcd(set_RX8010SJ_time->time.Second);
	Time_set.time.Minute = RTC_BinToBcd(set_RX8010SJ_time->time.Minute);
	Time_set.time.Hour = RTC_BinToBcd(set_RX8010SJ_time->time.Hour);
	Time_set.date.weekday = 0x01<<RTC_Cal_Week(set_RX8010SJ_time->date.year,set_RX8010SJ_time->date.month,set_RX8010SJ_time->date.day);
	Time_set.date.day = RTC_BinToBcd(set_RX8010SJ_time->date.day);
	Time_set.date.month = RTC_BinToBcd(set_RX8010SJ_time->date.month);
	Time_set.date.year = RTC_BinToBcd(set_RX8010SJ_time->date.year);
	BSP_IIC_Send_Data(RX8010SJ_IIC_W_ADDR,RX8010_ADDR_SECOND,(uint8_t *)&Time_set.time.Second,7);
	/*修改控制寄存器禁止写时间*/
	temp_u8 = 0x00;
	BSP_IIC_Send_Data(RX8010SJ_IIC_W_ADDR,RX8010_ADDR_CTRL_REG,(uint8_t *)&temp_u8,1);
}
/*---------------------------------------------------------------------------------------
函数名:    Read_From_RX8010SJ()
函数功能:  读实时时钟
参数:无
返回值:无
备注:
----------------------------------------------------------------------------------------*/
RX8010SJ_Info Read_From_RX8010SJ(void)
{
	RX8010SJ_Info Time_read={0};
	static uint8_t rx8010_buffer[7]={0};
	BSP_IIC_Read_Data(RX8010SJ_IIC_R_ADDR,RX8010_ADDR_SECOND,(uint8_t *)&rx8010_buffer[0],7);
	Time_read.time.Second 	= RTC_BcdToBin(rx8010_buffer[0],BCD_MinAndSec);
	Time_read.time.Minute 	= RTC_BcdToBin(rx8010_buffer[1],BCD_MinAndSec); 
	Time_read.time.Hour		= RTC_BcdToBin(rx8010_buffer[2],BCD_HourAndDay); 
	Time_read.date.weekday	= RTC_Get_Week(rx8010_buffer[3]); 
	Time_read.date.day		= RTC_BcdToBin(rx8010_buffer[4],BCD_HourAndDay); 
	Time_read.date.month	= RTC_BcdToBin(rx8010_buffer[5],BCD_Months); 
	Time_read.date.year		= RTC_BcdToBin(rx8010_buffer[6],BCD_Years);

	return (Time_read);
}

2.dev_rx8010sj.h

#ifndef __DEV_RX8010SJ_H
#define __DEV_RX8010SJ_H
#include "includes.h"
/************宏定义***************/
#define RX8010SJ_IIC_W_ADDR			0x64    //写地址
#define RX8010SJ_IIC_R_ADDR			0x65    //读地址

/* RX8010SJ芯片里时间和日期寄存器的地址
 * 从10H~16H共七个8位寄存器依次包含:秒(0~59)、分(0~59)、时(0~23)、
 * 日(1~31)、周几(0~6)、月份(1~12)、年份(0~99)
 */
#define RX8010_ADDR_SECOND      (0x10)  
#define RX8010_ADDR_MINUTE      (0x11)  
#define RX8010_ADDR_HOUR        (0x12)  
#define RX8010_ADDR_WEEK        (0x13)  
#define RX8010_ADDR_DAY         (0x14)  
#define RX8010_ADDR_MONTH       (0x15)  
#define RX8010_ADDR_YEAR        (0x16)  
#define RX8010_ADDR_RSV17       (0x17)  
#define RX8010_ADDR_ALM_MINUTE  (0x18)  
#define RX8010_ADDR_ALM_HOUR    (0x19)  
#define RX8010_ADDR_ALM_WEEK    (0x1A)  
#define RX8010_ADDR_ALM_DATE    (0x1A)  
#define RX8010_ADDR_TMR_CNT0    (0x1B)  
#define RX8010_ADDR_TMR_CNT1    (0x1C)  
#define RX8010_ADDR_EXT_REG     (0x1D)  
#define RX8010_ADDR_FLAG_REG    (0x1E)  
#define RX8010_ADDR_CTRL_REG    (0x1F)  

#define RX8010_ADDR_RSV1        (0x30)
#define RX8010_ADDR_RSV2        (0x31)
#define RX8010_ADDR_RSV3        (0x32)
/* RX8010SJ芯片时间寄存器最大位数
 * 秒和分最多7Bits
 * 时和日期最多6Bits
 */
#define BCD_MinAndSec       ((uint8_t)0x7F)  // 取低7位
#define BCD_HourAndDay      ((uint8_t)0x3F)  // 取低6位
#define BCD_Weekday         ((uint8_t)0x07)  // 取低3位
#define BCD_Months          ((uint8_t)0x1F)  // 取低5位
#define BCD_Years           ((uint8_t)0xFF)  // 取低8位
/*************结构体、枚举定义*****************/
typedef struct
{
    struct
    {
        uint8_t Second;
        uint8_t Minute;
        uint8_t Hour;
    } time;

    struct
    {
        uint8_t weekday;
        uint8_t day;
        uint8_t month;
        uint8_t year;
    } date;

} RX8010SJ_Info;

extern RX8010SJ_Info RTC_Message;

/************函数声明***************/
static uint8_t RTC_BinToBcd(uint8_t BinValue);
static uint8_t RTC_BcdToBin(uint8_t BCDValue,uint8_t xRegister);
uint8_t RTC_Cal_Week(uint16_t year,uint8_t month,uint8_t day);
uint8_t RTC_Get_Week(uint8_t Weekday);
void Dev_RX8010SJ_Init(void);
void Write_To_RX8010SJ(RX8010SJ_Info* set_RX8010SJ_time);
RX8010SJ_Info Read_From_RX8010SJ(void);
#endif

HAL库实现IIC驱动,包括IIC的初始化配置以及IIC收发函数

3.bsp_iic.c

#include "bsp_iic.h"
#ifdef  USE_HARDWARE_IIC
I2C_HandleTypeDef	IIC1Handle;//IIC1句柄
/*---------------------------------------------------------------------------------------
函数名:  BSP_IIC_INIT()
函数功能:IIC总线初始化
参数:无
返回值:无
备注:
----------------------------------------------------------------------------------------*/
void BSP_IIC_INIT()
{
	IIC1Handle.Instance             = I2C1;
	IIC1Handle.Init.Timing          = IIC_SPEED; 
	IIC1Handle.Init.OwnAddress1     = 0x00;
	IIC1Handle.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
	IIC1Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
	IIC1Handle.Init.OwnAddress2     = 0x00;
	IIC1Handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
	IIC1Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
	IIC1Handle.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE;
	HAL_I2C_Init(&IIC1Handle);

	HAL_I2CEx_AnalogFilter_Config(&IIC1Handle, I2C_ANALOGFILTER_ENABLE);  
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	if(i2cHandle->Instance==I2C1)
	{
		__HAL_RCC_I2C1_CLK_ENABLE();            //IIC1时钟使能
		
		//硬件IIC引脚配置
		//PB7_IIC2_SCL
		GPIO_InitStruct.Pin       = GPIO_IIC_SCL_PIN;
		GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;        //复用推挽输出
		GPIO_InitStruct.Pull      = GPIO_NOPULL;            //无上下拉,外部硬件上拉
		GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;   //高速
		GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;          //复用为IIC1
		HAL_GPIO_Init(GPIO_IIC_SCL_PORT, &GPIO_InitStruct);
		//PB7_IIC2_SDA
		GPIO_InitStruct.Pin       = GPIO_IIC_SDA_PIN;
		HAL_GPIO_Init(GPIO_IIC_SDA_PORT, &GPIO_InitStruct);
		bsp_GPIOOutHandleStruct.PinNum+=2;

		HAL_I2CEx_ConfigAnalogFilter(&IIC1Handle,I2C_ANALOGFILTER_ENABLE); //使能模拟滤波
		__HAL_RCC_I2C4_FORCE_RESET();
		__HAL_RCC_I2C4_RELEASE_RESET();
	}
}
/*---------------------------------------------------------------------------------------
函数名:  BSP_IIC_Send_Byte()
函数功能:IIC发送一个字节
参数:DevAddress设备地址,Txdata 发送数据
返回值:1:从机有应答 0:从机无应答	
备注:
----------------------------------------------------------------------------------------*/				 				   	 
void BSP_IIC_Send_Byte(uint16_t DevAddress,uint8_t Txdata)
{              
	uint8_t Temp_data=Txdata;    
	if(HAL_I2C_Master_Transmit(&IIC1Handle,DevAddress,(uint8_t *)&Temp_data,1,0xFFFF) != HAL_OK)
	{
		printf("IIC Send error\r\n");
	}
}
/*---------------------------------------------------------------------------------------
函数名:  BSP_IIC_Read_Byte()
函数功能:IIC读取一个字节数据
参数:ack:0,无应答;1,应答
返回值:无
备注:
----------------------------------------------------------------------------------------*/   
uint8_t BSP_IIC_Read_Byte(uint16_t DevAddress)
{
	uint8_t Temp_data;    
	if(HAL_I2C_Master_Receive(&IIC1Handle,DevAddress,(uint8_t *)&Temp_data,1,0xFFFF) != HAL_OK)
	{
		printf("IIC Recive error\r\n");
	}
	return Temp_data;
}

/*---------------------------------------------------------------------------------------
函数名:  BSP_IIC_Send_Data()
函数功能:IIC连续发送数据
参数:	  DevAddress设备地址,MemAddress寄存器地址,pData数据地址,Size数据长度
返回值
备注:
----------------------------------------------------------------------------------------*/				 				   	 
uint8_t BSP_IIC_Send_Data(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{                    
	if(HAL_I2C_Mem_Write(&IIC1Handle,DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT,pData,Size,0xFFFF) != HAL_OK)
	{
		printf("IIC Send error\r\n");
	}
	return 0;
}
/*---------------------------------------------------------------------------------------
函数名:  BSP_IIC_Read_Data()
函数功能:IIC连续读取数据
参数:
返回值:无
备注:
----------------------------------------------------------------------------------------*/   
uint8_t BSP_IIC_Read_Data(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{     
	if(HAL_I2C_Mem_Read(&IIC1Handle,DevAddress,MemAddress, I2C_MEMADD_SIZE_8BIT,pData,Size,0xFFFF) != HAL_OK)
	{
		printf("IIC Recive error\r\n");
	}
	return 0;
}	
#endif

4.bsp_iic.h

#ifndef __BSP_IIC_H
#define __BSP_IIC_H
/************头文件包含***************/
#include "includes.h"
#ifdef USE_HARDWARE_IIC
/************宏定义***************/
#define IIC_SPEED      0x40604E73  //硬件IIC速率设置,100k
/************函数声明***************/
void BSP_IIC_INIT(void);
void BSP_IIC_Send_Byte(uint16_t DevAddress,uint8_t Txdata);
uint8_t BSP_IIC_Read_Byte(uint16_t DevAddress);
uint8_t BSP_IIC_Send_Data(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size);
uint8_t BSP_IIC_Read_Data(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size);
extern I2C_HandleTypeDef	IIC1Handle;//IIC1句柄
#endif
#endif

三.设计注意点

1.RX8010SJ的数据寄存器,除了周之外,都是BCD格式。设置时间需要转换为BCD码,读取RTC后根据自身需求进行数据格式转换

2.RX8010SJ的周数据不是BCD码格式,需要单独进行处理

四.测试建议

        驱动完成后,首先设置当前时间,每间隔1秒读取时间并打印,观察时间是否正确。多测试跨分钟、小时、天、月、年等时间节点,看跨越是否正常。

结语

        经测试,该套驱动可以正常驱动RX8010SJ芯片。本驱动相对较为简单,仅适用于功能快速开发,未经过长时间可靠性测试。更高深应用可参考RX8010SJ芯片手册。

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ili9341是一种常见的液晶显示屏控制器,常用于嵌入式系统中。它可以通过STM32HAL库来进行驱动。 首先,我们需要在STM32HAL库中配置GPIO引脚,用于ILI9341的数据和控制信号。通常需要使用SPI接口进行通信,因此需要配置对应的SPI引脚,并初始化SPI外设。使用HAL库的函数,我们可以简单地设置GPIO引脚的模式、速度和中断等。 接下来,我们需要编写驱动代码以实现ILI9341与STM32之间的通信。HAL库中提供了一系列的SPI函数,可以用于发送和接收数据。通过配置控制寄存器和数据寄存器,我们可以向ILI9341发送命令和数据。 在ILI9341的初始化过程中,我们需要按照其数据手册所规定的步骤进行配置。例如,设置像素格式、方向、颜色模式等。还需要设置ILI9341的画布大小,以便正确显示图像。 一旦ILI9341完成初始化,我们就可以使用HAL库提供的函数来绘制图形、显示文本等操作。例如,可以使用HAL库的函数在屏幕上绘制点、直线、矩形、圆等图形。还可以使用HAL库的函数来显示文本,设置字体、大小和颜色等。 总之,通过使用STM32HAL库驱动ILI9341,我们可以方便地控制并显示图像和文本。该库提供了一系列的函数,用于配置引脚、初始化SPI外设并实现与ILI9341的通信。这样,开发人员可以轻松地在嵌入式系统中使用ILI9341,并实现各种复杂的显示功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值