first commit

This commit is contained in:
2023-12-11 21:45:06 +08:00
commit eaa7cc0eea
180 changed files with 60911 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_adc
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "ch32v30x.h"
#include "ch32v30x_adc.h"
#include "zf_driver_adc.h"
#include "zf_driver_gpio.h"
#include "zf_common_debug.h"
static ADC_TypeDef *adc_index[2] = {ADC1, ADC2};
static uint8 adc_resolution[2] = {ADC_12BIT, ADC_12BIT};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 ADC转换一次
// 参数说明 ch 选择ADC通道
// 参数说明 resolution 分辨率(8位 10位 12位)
// 返回参数 void
// 使用示例 adc_convert(ADC_IN0_A0, ADC_8BIT); //采集A0端口返回8位分辨率的AD值
//-------------------------------------------------------------------------------------------------------------------
uint16 adc_convert (adc_channel_enum ch)
{
uint8 adc = ((ch & 0xF000) >> 12);
uint8 adc_ch = (uint8)(ch >> 8) & 0xF;
ADC_RegularChannelConfig(adc_index[adc], adc_ch, 1, ADC_SampleTime_41Cycles5); // 使能对应通道
ADC_SoftwareStartConvCmd(adc_index[adc], ENABLE); // 开始数据转换
while(!ADC_GetFlagStatus(adc_index[adc], ADC_FLAG_EOC )); // 等待数据转换完成
return ((adc_index[adc]->RDATAR) >> adc_resolution[adc]); // 读取数据
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 ADC转换N次平均值滤波
// 参数说明 ch 选择ADC通道
// 参数说明 resolution 分辨率(8位 10位 12位)
// 参数说明 count 转换次数
// 返回参数 void
// 使用示例 adc_mean_filter(ADC_IN0_A0, ADC_8BIT,5); //采集A0端口返回8位分辨率的AD值采集五次取平均值
//-------------------------------------------------------------------------------------------------------------------
uint16 adc_mean_filter_convert (adc_channel_enum ch, const uint8 count)
{
uint8 i;
uint32 sum;
zf_assert(count);//断言次数不能为0
sum = 0;
for(i=0; i<count; i++)
{
sum += adc_convert(ch);
}
sum = sum/count;
return sum;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 ADC初始化
// 参数说明 adc_ch adc_ch通道(可选择范围由zf_adc.h内ADC_CH_enum枚举值确定)
// 返回参数 void
// 使用示例 adc_init(ADC_IN0_A0);//初始化A0引脚为ADC功能
//-------------------------------------------------------------------------------------------------------------------
void adc_init (adc_channel_enum ch, adc_resolution_enum resolution)
{
ADC_InitTypeDef ADC_InitStructure = {0};
uint8 adc = ((ch & 0xF000) >> 12);
gpio_init(ch&0xFF, GPI, 0, GPI_ANAOG_IN); // GPIO初始化
if(adc == 0)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE ); // 使能ADC1通道时钟
}
else if(adc == 1)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2 , ENABLE ); // 使能ADC2通道时钟
}
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
// if(system_clock > 84000000) RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 设置ADC分频因子ADC最大速率不能超过14M
// else RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_DeInit(adc_index[adc]);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC工作模式:ADC1工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; // 顺序进行规则转换的ADC通道的数目
ADC_Init(adc_index[adc], &ADC_InitStructure); // 根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(adc_index[adc], ENABLE); // 使能指定的ADC1
ADC_BufferCmd(adc_index[adc], DISABLE); // disable buffer
ADC_ResetCalibration(adc_index[adc]); // 使能复位校准
while(ADC_GetResetCalibrationStatus(adc_index[adc])); // 等待复位校准结束
ADC_StartCalibration(adc_index[adc]); // 开启AD校准
while(ADC_GetCalibrationStatus(adc_index[adc])); // 等待校准结束
//ADC_BufferCmd(ADC1, ENABLE); // enable buffer
adc_resolution[adc] = resolution; // 记录ADC精度 将在采集时使用
}

View File

@@ -0,0 +1,102 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_adc
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_adc_h
#define _zf_driver_adc_h
#include "zf_driver_gpio.h"
#include "zf_common_typedef.h"
//CH32V307只有一个ADC可以分时复用在很多个通道上面
//此枚举定义不允许用户修改
typedef enum // 枚举ADC通道
{
ADC1_IN0_A0 = 0x0000, // 0x 0[ADC1] 0[CH00] 00[A0]
ADC1_IN1_A1 = 0x0101, // 0x 0[ADC1] 1[CH00] 01[A1]
ADC1_IN2_A2 = 0x0202, // 0x 0[ADC1] 2[CH00] 02[A2]
ADC1_IN3_A3 = 0x0303, // 0x 0[ADC1] 3[CH00] 03[A3]
ADC1_IN4_A4 = 0x0404, // 0x 0[ADC1] 4[CH00] 04[A4]
ADC1_IN5_A5 = 0x0505, // 0x 0[ADC1] 5[CH00] 05[A5]
ADC1_IN6_A6 = 0x0606, // 0x 0[ADC1] 6[CH00] 06[A6]
ADC1_IN7_A7 = 0x0707, // 0x 0[ADC1] 7[CH00] 07[A7]
ADC1_IN8_B0 = 0x0820, // 0x 0[ADC1] 8[CH00] 20[B0]
ADC1_IN9_B1 = 0x0921, // 0x 0[ADC1] 9[CH00] 21[B1]
ADC1_IN10_C0 = 0x0A40, // 0x 0[ADC1] A[CH00] 40[C0]
ADC1_IN11_C1 = 0x0B41, // 0x 0[ADC1] B[CH00] 41[C1]
ADC1_IN12_C2 = 0x0C42, // 0x 0[ADC1] C[CH00] 42[C2]
ADC1_IN13_C3 = 0x0D43, // 0x 0[ADC1] D[CH00] 43[C3]
ADC1_IN14_C4 = 0x0E44, // 0x 0[ADC1] E[CH00] 44[C4]
ADC1_IN15_C5 = 0x0F45, // 0x 0[ADC1] F[CH00] 45[C5]
ADC2_IN0_A0 = 0x1000, // 0x 1[ADC2] 0[CH00] 00[A0]
ADC2_IN1_A1 = 0x1101, // 0x 1[ADC2] 1[CH00] 01[A1]
ADC2_IN2_A2 = 0x1202, // 0x 1[ADC2] 2[CH00] 02[A2]
ADC2_IN3_A3 = 0x1303, // 0x 1[ADC2] 3[CH00] 03[A3]
ADC2_IN4_A4 = 0x1404, // 0x 1[ADC2] 4[CH00] 04[A4]
ADC2_IN5_A5 = 0x1505, // 0x 1[ADC2] 5[CH00] 05[A5]
ADC2_IN6_A6 = 0x1606, // 0x 1[ADC2] 6[CH00] 06[A6]
ADC2_IN7_A7 = 0x1707, // 0x 1[ADC2] 7[CH00] 07[A7]
ADC2_IN8_B0 = 0x1820, // 0x 1[ADC2] 8[CH00] 20[B0]
ADC2_IN9_B1 = 0x1921, // 0x 1[ADC2] 9[CH00] 21[B1]
ADC2_IN10_C0 = 0x1A40, // 0x 1[ADC2] A[CH00] 40[C0]
ADC2_IN11_C1 = 0x1B41, // 0x 1[ADC2] B[CH00] 41[C1]
ADC2_IN12_C2 = 0x1C42, // 0x 1[ADC2] C[CH00] 42[C2]
ADC2_IN13_C3 = 0x1D43, // 0x 1[ADC2] D[CH00] 43[C3]
ADC2_IN14_C4 = 0x1E44, // 0x 1[ADC2] E[CH00] 44[C4]
ADC2_IN15_C5 = 0x1F45, // 0x 1[ADC2] F[CH00] 45[C5]
}adc_channel_enum;
//此枚举定义不允许用户修改
typedef enum // 枚举ADC通道
{
ADC_8BIT = 4, //8位分辨率
ADC_9BIT = 3, //9位分辨率
ADC_10BIT = 2, //10位分辨率
ADC_11BIT = 1, //11位分辨率
ADC_12BIT = 0, //12位分辨率
}adc_resolution_enum;
uint16 adc_convert (adc_channel_enum ch);
uint16 adc_mean_filter_convert (adc_channel_enum ch, const uint8 count);
void adc_init (adc_channel_enum ch, adc_resolution_enum resolution);
#endif

View File

@@ -0,0 +1,85 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_delay
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "ch32v30x.h"
#include "zf_common_clock.h"
#include "zf_driver_delay.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 system 延时函数 ms 级别
// 参数说明 time 需要延时的时间 ms 级别
// 返回参数 void
// 使用示例 system_delay_ms(100);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void system_delay_ms (uint32 num)
{
SysTick->SR &= ~(1 << 0);
SysTick->CMP = (uint64_t)(system_clock/8000) * num;
SysTick->CTLR |= (1 << 4);
SysTick->CTLR |= (1 << 5) | (1 << 0);
while((SysTick->SR & (1 << 0)) != (1 << 0));
SysTick->CTLR &= ~(1 << 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 system 延时函数 us 级别
// 参数说明 time 需要延时的时间 us 级别
// 返回参数 void
// 使用示例 system_delay_us(100);
// 备注信息 受限于程序运行跳转 此延时会比输入值高出一些
//-------------------------------------------------------------------------------------------------------------------
void system_delay_us (uint32 num)
{
SysTick->SR &= ~(1 << 0);
SysTick->CMP = (uint64_t)(system_clock/8000000) * num;
SysTick->CTLR |= (1 << 4);
SysTick->CTLR |= (1 << 5) | (1 << 0);
while((SysTick->SR & (1 << 0)) != (1 << 0));
SysTick->CTLR &= ~(1 << 0);
}

View File

@@ -0,0 +1,45 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_delay
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_delay_h
#define _zf_driver_delay_h
#include "zf_common_clock.h"
#include "zf_common_typedef.h"
void system_delay_ms (uint32 time);
void system_delay_us (uint32 time);
#endif

View File

@@ -0,0 +1,106 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_dvp
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_delay.h"
#include "zf_driver_gpio.h"
#include "zf_driver_dvp.h"
//vuint32 frame_cnt = 0;
//vuint32 addr_cnt = 0;
//vuint32 href_cnt = 0;
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 dvp接口引脚初始化
// 参数说明 dvp_d0到dvp_d0 摄像头D0-D7引脚
// 参数说明 dvp_pclk 摄像头PCLK引脚
// 参数说明 dvp_vsync 摄像头vysnc引脚
// 参数说明 dvp_herf 摄像头herf引脚
// 返回参数 void
// 使用示例 内部使用,用户无需关心
//-------------------------------------------------------------------------------------------------------------------
void dvp_gpio_init(
uint8 dvp_d0,uint8 dvp_d1,uint8 dvp_d2,uint8 dvp_d3,
uint8 dvp_d4,uint8 dvp_d5,uint8 dvp_d6,uint8 dvp_d7,
uint8 dvp_pclk,uint8 dvp_vsync,uint8 dvp_hsync)
{
//DVP_D0 到 DVP_ D7
gpio_init(dvp_d0, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d1, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d2, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d3, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d4, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d5, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d6, GPI, 0, GPI_PULL_UP);
gpio_init(dvp_d7, GPI, 0, GPI_PULL_UP);
//DVP_VSYNC
gpio_init(dvp_vsync, GPI, 0, GPI_PULL_UP);
//DVP_PCLK
gpio_init(dvp_pclk, GPI, 0, GPI_PULL_UP);
//DVP_HSYNC
gpio_init(dvp_hsync, GPI, 0, GPI_PULL_UP);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 dvp接口初始化
// 参数说明 *image0 数据buff0的地址
// 参数说明 *image1 数据buff1的地址
// 参数说明 col_len 列长度
// 参数说明 row_len 行长度
// 返回参数 void
// 使用示例 内部使用,用户无需关心
//-------------------------------------------------------------------------------------------------------------------
void dvp_camera_init(uint32 *image0_addr, uint32 *image1_addr, uint16 col_len, uint16 row_len)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DVP, ENABLE);
// 使用8位采集模式PCLK上升沿采样数据HSYNC高电平有效VSYNC高电平数据有效使能DVP
DVP->CR0 = RB_DVP_D8_MOD | RB_DVP_V_POLAR | RB_DVP_ENABLE;
// 捕获所有帧捕获完整图像连续模式使能DMA
DVP->CR1 = DVP_RATE_100P | RB_DVP_DMA_EN;
DVP->ROW_NUM = row_len; // rows行数
DVP->COL_NUM = col_len; // cols列数
DVP->DMA_BUF0 = (uint32)image0_addr; // DMA addr0
DVP->DMA_BUF1 = (uint32)image1_addr; // DMA addr1
// 使能中断
DVP->IER = RB_DVP_IE_FRM_DONE; // 开启帧接收完成中断
interrupt_set_priority(DVP_IRQn, 0x0);
interrupt_enable(DVP_IRQn);
}

View File

@@ -0,0 +1,54 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_dvp
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_dvp_h
#define _zf_driver_dvp_h
#include "ch32v30x.h"
#include "stdio.h"
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "zf_common_interrupt.h"
#include "zf_common_typedef.h"
void dvp_camera_init(uint32 *image0_addr, uint32 *image1_addr, uint16 col_len, uint16 row_len);
void dvp_gpio_init(
uint8 dvp_d0,uint8 dvp_d1,uint8 dvp_d2,uint8 dvp_d3,
uint8 dvp_d4,uint8 dvp_d5,uint8 dvp_d6,uint8 dvp_d7,
uint8 dvp_pclk,uint8 dvp_vsync,uint8 dvp_hsync);
#endif

View File

@@ -0,0 +1,261 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_encoder
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
#include "zf_driver_timer.h"
#include "zf_driver_encoder.h"
static volatile uint8 encoder_dir_pin[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 定时器编码器解码取值
// 参数说明 timer_ch 定时器枚举体
// 返回参数 void
// 备注信息
// 使用示例 encoder_get_count(TIM2_ENCOEDER) // 获取定时器2的采集到的编码器数据
//-------------------------------------------------------------------------------------------------------------------
int16 encoder_get_count(encoder_index_enum encoder_n)
{
int16 result = 0;
int16 return_value = 0;
switch(encoder_n)
{
case TIM1_ENCOEDER: result = TIM1->CNT; break;
case TIM2_ENCOEDER: result = TIM2->CNT; break;
case TIM3_ENCOEDER: result = TIM3->CNT; break;
case TIM4_ENCOEDER: result = TIM4->CNT; break;
case TIM5_ENCOEDER: result = TIM5->CNT; break;
case TIM8_ENCOEDER: result = TIM8->CNT; break;
case TIM9_ENCOEDER: result = TIM9->CNT; break;
case TIM10_ENCOEDER: result = TIM10->CNT; break;
default: result = 0; break;
}
if(0xFF == encoder_dir_pin[encoder_n])
{
return_value = result;
}
else
{
if(!gpio_get_level((gpio_pin_enum)encoder_dir_pin[encoder_n]))
{
return_value = -result;
}
else
{
return_value = result;
}
}
return return_value;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 定时器的计数器清空
// 参数说明 timer_ch 定时器枚举体
// 返回参数 void
// 备注信息
// 使用示例 encoder_clear_count(TIM1_ENCOEDER) //清除定时器1采集到的编码器数据
//-------------------------------------------------------------------------------------------------------------------
void encoder_clear_count(encoder_index_enum encoder_n)
{
switch(encoder_n)
{
case TIM1_ENCOEDER: TIM1->CNT = 0; break;
case TIM2_ENCOEDER: TIM2->CNT = 0; break;
case TIM3_ENCOEDER: TIM3->CNT = 0; break;
case TIM4_ENCOEDER: TIM4->CNT = 0; break;
case TIM5_ENCOEDER: TIM5->CNT = 0; break;
case TIM8_ENCOEDER: TIM8->CNT = 0; break;
case TIM9_ENCOEDER: TIM9->CNT = 0; break;
case TIM10_ENCOEDER: TIM10->CNT = 0; break;
default: break;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 编码器解码初始化
// 参数说明 timer_ch 定时器枚举体
// 参数说明 phaseA 通道A以及引脚
// 参数说明 phaseB 通道B以及引脚
// 返回参数 void
// 备注信息 推荐使用正交解码编码器。
// 使用示例 encoder_init_quad(TIM1_ENCOEDER, TIM1_CH1_ENCOEDER_E9, TIM1_CH2_ENCOEDER_E11)
// // 使用定时器1 做正交编码器解码, 通道1引脚号E9通道2引脚号E11
//-------------------------------------------------------------------------------------------------------------------
void encoder_quad_init(encoder_index_enum encoder_n, encoder_channel_enum ch1_pin, encoder_channel_enum ch2_pin)
{
uint32 register_temp = 0;
TIM_TypeDef *tim_index;
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// 这里是检查是否有重复使用定时器
// 比如初始化了 TIM1_PWM 然后又初始化成 TIM1_ENCODER 这种用法是不允许的
zf_assert(timer_funciton_check((timer_index_enum)encoder_n, TIMER_FUNCTION_ENCODER));
zf_assert((ch1_pin >> 12) == (encoder_n)); // ch1_pin 与 ch2_pin 必须与 encoder_n 匹配
zf_assert((ch2_pin >> 12) == (encoder_n)); // ch1_pin 与 ch2_pin 必须与 encoder_n 匹配
timer_clock_enable(encoder_n); // 定时器时钟使能
gpio_init((gpio_pin_enum)(ch1_pin & 0xFF), GPI, 0, GPI_PULL_UP); // 初始化引脚
gpio_init((gpio_pin_enum)(ch2_pin & 0xFF), GPI, 0, GPI_PULL_UP); // 初始化引脚
//encoder_dir_pin[encoder_n] = (ch1_pin &0xFF); // 将方向引脚号存入数组中
switch(encoder_n)
{
case TIM1_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM2_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM3_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM4_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM5_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM8_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM9_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM10_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
default: register_temp = 1;
}
// 开启复用功能
if((ch1_pin >> 8) == 0x03) GPIO_PinRemapConfig(GPIO_FullRemap_TIM1, ENABLE);
else if((ch1_pin >> 8) == 0x11) GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
else if((ch1_pin >> 8) == 0x22) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
else if((ch1_pin >> 8) == 0x23) GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
else if((ch1_pin >> 8) == 0x31) GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
else if((ch1_pin >> 8) == 0x71) GPIO_PinRemapConfig(GPIO_Remap_TIM8, ENABLE);
else if((ch1_pin >> 8) == 0x83) GPIO_PinRemapConfig(GPIO_FullRemap_TIM9, ENABLE);
else if((ch1_pin >> 8) == 0x91) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM10, ENABLE);
else if((ch1_pin >> 8) == 0x93) GPIO_PinRemapConfig(GPIO_FullRemap_TIM10, ENABLE);
if(!register_temp)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO复用功能模块时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器
TIM_TimeBaseInit(tim_index, &TIM_TimeBaseStructure); // 初始化结构体
TIM_ITRxExternalClockConfig(tim_index, TIM_TS_TI2FP2); // 配置外部触发,否则不会计数
TIM_Cmd(tim_index, ENABLE); // 定时器使能
TIM_EncoderInterfaceConfig(
tim_index,
TIM_EncoderMode_TI2 ,
TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising); // 使用编码器模式, T2计数 ,T1判断方向, 上升沿计数
TIM_Cmd(tim_index, ENABLE); // 定时器使能
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 编码器解码初始化
// 参数说明 timer_ch 定时器枚举体
// 参数说明 phaseA 通道A以及引脚
// 参数说明 phaseB 通道B以及引脚
// 返回参数 void
// 推荐使用正交解码编码器。
// 使用示例 encoder_init_dir(TIM1_ENCOEDER, TIM1_CH1_ENCOEDER_E9, TIM1_CH2_ENCOEDER_E11)
// // 使用定时器1 做带方向的编码器解码, 通道1方向信号引脚E9通道2脉冲信号引脚E11
//-------------------------------------------------------------------------------------------------------------------
void encoder_dir_init(encoder_index_enum encoder_n, encoder_channel_enum ch1_pin, encoder_channel_enum ch2_pin)
{
uint32 register_temp = 0;
TIM_TypeDef *tim_index;
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// 这里是检查是否有重复使用定时器
// 比如初始化了 TIM1_PWM 然后又初始化成 TIM1_ENCODER 这种用法是不允许的
zf_assert(timer_funciton_check((timer_index_enum)encoder_n, TIMER_FUNCTION_ENCODER));
zf_assert((ch1_pin & (encoder_n << 12)) == (encoder_n << 12)); // ch1_pin 与 ch2_pin 必须与 encoder_n 匹配
zf_assert((ch2_pin & (encoder_n << 12)) == (encoder_n << 12)); // ch1_pin 与 ch2_pin 必须与 encoder_n 匹配
timer_clock_enable(encoder_n); // 定时器时钟使能
gpio_init((gpio_pin_enum)(ch1_pin & 0xFF), GPI, 0, GPI_PULL_UP); // 初始化引脚
gpio_init((gpio_pin_enum)(ch2_pin & 0xFF), GPI, 0, GPI_PULL_UP); // 初始化引脚
encoder_dir_pin[encoder_n] = (ch1_pin &0xFF); // 将方向引脚号存入数组中
switch(encoder_n)
{
case TIM1_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM2_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM3_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM4_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM5_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM8_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM9_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM10_ENCOEDER: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
default: register_temp = 1;
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO复用功能模块时钟
// 开启复用功能
if((ch1_pin >> 8) == 0x03) GPIO_PinRemapConfig(GPIO_FullRemap_TIM1, ENABLE);
else if((ch1_pin >> 8) == 0x11) GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
else if((ch1_pin >> 8) == 0x22) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
else if((ch1_pin >> 8) == 0x23) GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
else if((ch1_pin >> 8) == 0x31) GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
else if((ch1_pin >> 8) == 0x71) GPIO_PinRemapConfig(GPIO_Remap_TIM8, ENABLE);
else if((ch1_pin >> 8) == 0x83) GPIO_PinRemapConfig(GPIO_FullRemap_TIM9, ENABLE);
else if((ch1_pin >> 8) == 0x91) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM10, ENABLE);
else if((ch1_pin >> 8) == 0x93) GPIO_PinRemapConfig(GPIO_FullRemap_TIM10, ENABLE);
if(!register_temp)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器
TIM_TimeBaseInit(tim_index, &TIM_TimeBaseStructure); // 初始化结构体
TIM_ITRxExternalClockConfig(tim_index, TIM_TS_TI2FP2); // 配置外部触发,否则不会计数
TIM_ETRConfig(tim_index, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 15); // 采样频率Fsampling=Fdts/32N=8
TIM_Cmd(tim_index, ENABLE); // 定时器使能
}
}

View File

@@ -0,0 +1,176 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_encoder
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_encoder_h
#define _zf_driver_encoder_h
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_tim.h"
#include "zf_common_debug.h"
#include "zf_common_typedef.h"
typedef enum // TIMER引脚枚举
{
// MAP0 默认映射
// MAP1 重映射
// MAP2 部分映射
// MAP3 完全映射
//----------定时器1----------
// 以下为TIM1编码器的一组通道不允许映射引脚混用。
// 例如TIM1_ENCOEDER_MAP_CH1_A8与TIM1_ENCOEDER_MAP_CH2_E11不能一起使用。
// 只能是TIM1_ENCOEDER_MAP_CH1_A8与TIM1_ENCOEDER_MAP_CH2_A9 同组映射引脚一起使用,
// 或者TIM1_ENCOEDER_MAP_CH1_E9与TIM1_ENCOEDER_MAP_CH2_E11 同组映射引脚一起使用
// 默认映射
TIM1_ENCOEDER_MAP0_CH1_A8 = 0x0000 | A8, // 0x 0[TIM1] 0[MAP0] 08[A8 ]
TIM1_ENCOEDER_MAP0_CH2_A9 = 0x0000 | A9, // 0x 0[TIM1] 0[MAP0] 09[A9 ]
// 以下为TIM1编码器的一组通道不允许映射引脚混用。
// 完全映射
TIM1_ENCOEDER_MAP3_CH1_E9 = 0x0300 | E9, // 0x 0[TIM1] 3[MAP3] 89[E9 ]
TIM1_ENCOEDER_MAP3_CH2_E11 = 0x0300 | E11, // 0x 0[TIM1] 3[MAP3] 8B[E11]
//----------定时器2----------
// 以下为TIM2编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM2_ENCOEDER_MAP0_CH1_A0 = 0x1000 | A0, // 0x 1[TIM2] 0[MAP0] 00[A0 ]
TIM2_ENCOEDER_MAP0_CH2_A1 = 0x1000 | A1, // 0x 1[TIM2] 0[MAP0] 01[A1 ]
// 以下为TIM2编码器的一组通道不允许映射引脚混用。
// 重映射
TIM2_ENCOEDER_MAP1_CH1_A15 = 0x1100 | A15, // 0x 1[TIM2] 1[MAP1] 0F[A15]
TIM2_ENCOEDER_MAP1_CH2_B3 = 0x1100 | B3, // 0x 1[TIM2] 1[MAP1] 23[B3 ]
//----------定时器3----------
// 以下为TIM3编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM3_ENCOEDER_MAP0_CH1_A6 = 0x2000 | A6, // 0x 2[TIM3] 0[MAP0] 06[A6 ]
TIM3_ENCOEDER_MAP0_CH2_A7 = 0x2000 | A7, // 0x 2[TIM3] 0[MAP0] 07[A7 ]
// 以下为TIM3编码器的一组通道不允许映射引脚混用。
// 部分映射
TIM3_ENCOEDER_MAP2_CH1_B4 = 0x2200 | B4, // 0x 2[TIM3] 2[MAP2] 24[B4 ]
TIM3_ENCOEDER_MAP2_CH2_B5 = 0x2200 | B5, // 0x 2[TIM3] 2[MAP2] 25[B5 ]
// 以下为TIM3编码器的一组通道不允许映射引脚混用。
// 完全映射
TIM3_ENCOEDER_MAP3_CH1_C6 = 0x2300 | C6, // 0x 2[TIM3] 3[MAP3] 46[C6 ]
TIM3_ENCOEDER_MAP3_CH2_C7 = 0x2300 | C7, // 0x 2[TIM3] 3[MAP3] 47[C7 ]
//----------定时器4----------
// 以下为TIM4编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM4_ENCOEDER_MAP0_CH1_B6 = 0x3000 | B6, // 0x 3[TIM4] 0[MAP0] 26[B6 ]
TIM4_ENCOEDER_MAP0_CH2_B7 = 0x3000 | B7, // 0x 3[TIM4] 0[MAP0] 27[B7 ]
// 以下为TIM4编码器的一组通道不允许映射引脚混用。
// 重定向
TIM4_ENCOEDER_MAP1_CH1_D12 = 0x3100 | D12, // 0x 3[TIM4] 1[MAP1] 6C[D12]
TIM4_ENCOEDER_MAP1_CH2_D13 = 0x3100 | D13, // 0x 3[TIM4] 1[MAP1] 6D[D13]
//----------定时器5----------
// 以下为TIM5编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM5_ENCOEDER_MAP0_CH1_A0 = 0x4000 | A0, // 0x 4[TIM5] 0[MAP0] 00[A0 ]
TIM5_ENCOEDER_MAP0_CH2_A1 = 0x4000 | A1, // 0x 4[TIM5] 0[MAP0] 01[A1 ]
//----------定时器8----------
// 以下为TIM8编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM8_ENCOEDER_MAP0_CH1_C6 = 0x7000 | C6, // 0x 7[TIM8] 0[MAP0] 46[C6 ]
TIM8_ENCOEDER_MAP0_CH2_C7 = 0x7000 | C7, // 0x 7[TIM8] 0[MAP0] 47[C7 ]
// 以下为TIM8编码器的一组通道不允许映射引脚混用。
// 重映射
TIM8_ENCOEDER_MAP1_CH1_B6 = 0x7100 | B6, // 0x 7[TIM8] 1[MAP1] 26[B6 ]
TIM8_ENCOEDER_MAP1_CH2_B7 = 0x7100 | B7, // 0x 7[TIM8] 1[MAP1] 27[B7 ]
//----------定时器9----------
// 以下为TIM9编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM9_ENCOEDER_MAP0_CH1_A2 = 0x8000 | A2, // 0x 8[TIM9] 0[MAP0] 02[A2 ]
TIM9_ENCOEDER_MAP0_CH2_A3 = 0x8000 | A3, // 0x 8[TIM9] 0[MAP0] 03[A3 ]
// 以下为TIM9编码器的一组通道不允许映射引脚混用。
// 完全映射
TIM9_ENCOEDER_MAP3_CH1_D9 = 0x8300 | D9, // 0x 8[TIM9] 3[MAP3] 69[D9 ]
TIM9_ENCOEDER_MAP3_CH2_D11 = 0x8300 | D11, // 0x 8[TIM9] 3[MAP3] 6B[D11]
//----------定时器10----------
// 以下为TIM10编码器的一组通道不允许映射引脚混用。
// 默认映射
TIM10_ENCOEDER_MAP0_CH1_B8 = 0x9000 | B8, // 0x 9[TIM10] 0[MAP0] 28[B8]
TIM10_ENCOEDER_MAP0_CH2_B9 = 0x9000 | B9, // 0x 9[TIM10] 0[MAP0] 29[B9]
// 以下为TIM10编码器的一组通道不允许映射引脚混用。
// 部分映射
TIM10_ENCOEDER_MAP1_CH1_B3 = 0x9100 | B3, // 0x 9[TIM10] 1[MAP1] 23[B3]
TIM10_ENCOEDER_MAP1_CH2_B4 = 0x9100 | B4, // 0x 9[TIM10] 1[MAP1] 24[B4]
// 以下为TIM10编码器的一组通道不允许映射引脚混用。
// 完全映射
TIM10_ENCOEDER_MAP3_CH1_D1 = 0x9300 | D1, // 0x 9[TIM10] 3[MAP3] 41[D1]
TIM10_ENCOEDER_MAP3_CH2_D3 = 0x9300 | D3, // 0x 9[TIM10] 3[MAP3] 43[D3]
}encoder_channel_enum;
typedef enum
{
TIM1_ENCOEDER = 0,
TIM2_ENCOEDER,
TIM3_ENCOEDER,
TIM4_ENCOEDER,
TIM5_ENCOEDER,
TIM8_ENCOEDER = 7,
TIM9_ENCOEDER,
TIM10_ENCOEDER,
}encoder_index_enum;
int16 encoder_get_count (encoder_index_enum encoder_n);
void encoder_clear_count (encoder_index_enum encoder_n);
void encoder_quad_init (encoder_index_enum encoder_n, encoder_channel_enum ch1_pin, encoder_channel_enum ch2_pin);
void encoder_dir_init (encoder_index_enum encoder_n, encoder_channel_enum ch1_pin, encoder_channel_enum ch2_pin);
#endif

View File

@@ -0,0 +1,99 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_exti
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_common_interrupt.h"
#include "zf_driver_exti.h"
#include "zf_driver_gpio.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 EXTI 中断使能
// 参数说明 pin 选择 EXTI 引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 void
// 使用示例 exti_enable(A0);
//-------------------------------------------------------------------------------------------------------------------
void exti_enable (gpio_pin_enum pin)
{
EXTI->INTENR |= (0x00000001 << (pin&0x1F));
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 EXTI 中断失能
// 参数说明 pin 选择 EXTI 引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 void
// 使用示例 exti_disable(A0);
//-------------------------------------------------------------------------------------------------------------------
void exti_disable (gpio_pin_enum pin)
{
EXTI->INTENR &= ~(0x00000001 << (pin&0x1F));
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 EXTI 中断初始化 <同一下标的引脚不能同时初始化为外部中断输入 例如 A0 和 B0 不能同时初始化为外部中断输入>
// 参数说明 pin 选择 EXTI 引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 参数说明 trigger 选择触发的信号方式 [EXTI_TRIGGER_RISING/EXTI_TRIGGER_FALLING/EXTI_TRIGGER_BOTH]
// 返回参数 void
// 使用示例 exti_init(A0, EXTI_TRIGGER_RISING);
//-------------------------------------------------------------------------------------------------------------------
void exti_init (gpio_pin_enum pin, exti_trigger_enum trigger)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 复用时钟使能
gpio_init(pin, GPI, GPIO_HIGH, GPI_PULL_UP); // 初始化选中的引脚
GPIO_EXTILineConfig(pin >> 5, pin & 0x1F); // 选择哪一组GPIO做中断
EXTI_InitTypeDef EXTI_InitStructure = {0};
EXTI_InitStructure.EXTI_Line = 1 << (pin & 0x1F); // 引脚号配置
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 触发模式
EXTI_InitStructure.EXTI_Trigger = trigger; // 触发方式
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能或者失能
EXTI_Init(&EXTI_InitStructure);
if((pin&0x1F) < 1)
interrupt_enable(EXTI0_IRQn); // 使能 Line0 的中断响应
else if((pin&0x1F) < 2)
interrupt_enable(EXTI1_IRQn); // 使能 Line1 的中断响应
else if((pin&0x1F) < 3)
interrupt_enable(EXTI2_IRQn); // 使能 Line2 的中断响应
else if((pin&0x1F) < 4)
interrupt_enable(EXTI3_IRQn); // 使能 Line3 的中断响应
else if((pin&0x1F) < 5)
interrupt_enable(EXTI4_IRQn); // 使能 Line4 的中断响应
else if((pin&0x1F) < 10)
interrupt_enable(EXTI9_5_IRQn); // 使能 Line5-9 的中断响应
else
interrupt_enable(EXTI15_10_IRQn); // 使能 Line10-15 的中断响应
}

View File

@@ -0,0 +1,53 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_exti
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_exti_h_
#define _zf_driver_exti_h_
#include "zf_common_typedef.h"
#include "zf_driver_gpio.h"
typedef enum{ // 枚举 EXTI 触发信号 此枚举定义不允许用户修改
EXTI_TRIGGER_RISING = 0x08, // 上升沿触发模式
EXTI_TRIGGER_FALLING = 0x0C, // 下降沿触发模式
EXTI_TRIGGER_BOTH = 0x10, // 双边沿触发模式
}exti_trigger_enum;
void exti_enable (gpio_pin_enum pin);
void exti_disable (gpio_pin_enum pin);
void exti_init (gpio_pin_enum pin, exti_trigger_enum trigger);
#endif

View File

@@ -0,0 +1,291 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_flash
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_common_debug.h"
#include "zf_common_interrupt.h"
#include "zf_common_clock.h"
#include "zf_driver_flash.h"
flash_data_union flash_union_buffer[FLASH_DATA_BUFFER_SIZE]; // FLASH 操作的数据缓冲区
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 校验 FLASH 是否有数据
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 返回参数 uint8 1-有数据 0-没有数据 如果需要对有数据的区域写入新的数据则应该对所在扇区进行擦除操作
// 使用示例 flash_check(63, 3);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 flash_check (uint32 sector_num, uint32 page_num)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
uint8 return_state = 0;
uint16 temp_loop;
uint32 flash_addr = ((FLASH_BASE_ADDR+FLASH_SECTION_SIZE*sector_num+FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
uint32 primask = interrupt_global_disable();
//clock_reset(); // 复位时钟
//clock_set_freq(SYSTEM_CLOCK_120M); // 设置系统频率为120Mhz
for(temp_loop = 0; temp_loop < FLASH_PAGE_SIZE; temp_loop+=4) // 循环读取 Flash 的值
{
if( (*(__IO u32*) (flash_addr+temp_loop)) != 0xE339E339 ) // 该单片机擦除后如果不是 0xE339E339 那就是有值
{
return_state = 1;
break;
}
}
//clock_reset(); // 复位时钟
//clock_set_freq(system_clock); // 设置回原来的系统频率
interrupt_global_enable(primask);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 擦除一个扇区数据(4KB)
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 返回参数 uint8 1-表示失败 0-表示成功
// 使用示例 flash_erase_page(63, 3);
// 备注信息
// 标准擦除只能是擦一个扇区的数据4KB字节长度
//-------------------------------------------------------------------------------------------------------------------
uint8 flash_erase_sector (uint32 sector_num, uint32 page_num)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
uint8 return_state = 0;
static volatile FLASH_Status gFlashStatus = FLASH_COMPLETE;
uint32 flash_addr = ((FLASH_BASE_ADDR+FLASH_SECTION_SIZE*sector_num+FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
uint32 primask = interrupt_global_disable();
//clock_reset(); // 复位时钟
//clock_set_freq(SYSTEM_CLOCK_120M); // 设置系统频率为120Mhz
FLASH_Unlock(); // 解锁 Flash
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); // 清除操作标志
gFlashStatus = FLASH_ErasePage(flash_addr); // 擦除
FLASH_ClearFlag(FLASH_FLAG_EOP ); // 清楚操作标志
FLASH_Lock(); // 锁定 Flash
if(gFlashStatus != FLASH_COMPLETE) // 判断操作是否成功
{
return_state = 1;
}
//clock_reset(); // 复位时钟
//clock_set_freq(system_clock); // 设置回原来的系统频率
interrupt_global_enable(primask);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 读取一页
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 参数说明 buf 需要读取的数据地址 传入的数组类型必须为uint32
// 参数说明 len 需要写入的数据长度 参数范围 1-256
// 返回参数 void
// 使用示例 flash_read_page(63, 3, data_buffer, 256);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void flash_read_page (uint32 sector_num, uint32 page_num, uint32 *buf, uint16 len)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
zf_assert(len <= FLASH_DATA_BUFFER_SIZE);
uint16 temp_loop = 0;
uint32 flash_addr = 0;
flash_addr = ((FLASH_BASE_ADDR+FLASH_SECTION_SIZE*sector_num+FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
uint32 primask = interrupt_global_disable();
//clock_reset(); // 复位时钟
//clock_set_freq(SYSTEM_CLOCK_120M); // 设置系统频率为120Mhz
for(temp_loop = 0; temp_loop < len; temp_loop++) // 根据指定长度读取
{
*buf++ = *(__IO uint32*)(flash_addr+temp_loop*4); // 循环读取 Flash 的值
}
// 锁定 Flash
//clock_reset(); // 复位时钟
//clock_set_freq(system_clock); // 设置回原来的系统频率
interrupt_global_enable(primask);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 编程一页
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 参数说明 buf 需要写入的数据地址 传入的数组类型必须为 uint32
// 参数说明 len 需要写入的数据长度 参数范围 1-256
// 返回参数 uint8 1-表示失败 0-表示成功
// 使用示例 flash_write_page(63, 3, data_buffer, 256);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 flash_write_page (uint32 sector_num, uint32 page_num, const uint32 *buf, uint16 len)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
zf_assert(len <= FLASH_DATA_BUFFER_SIZE);
uint8 return_state = 0;
static volatile FLASH_Status gFlashStatus = FLASH_COMPLETE;
uint32 flash_addr = 0;
flash_addr = ((FLASH_BASE_ADDR+FLASH_SECTION_SIZE*sector_num+FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
if(flash_check(sector_num, page_num)) // 判断是否有数据 这里是冗余的保护 防止有人没擦除就写入
{
flash_erase_sector(sector_num, page_num); // 擦除这一扇区
}
uint32 primask = interrupt_global_disable();
//clock_reset(); // 复位时钟
//clock_set_freq(SYSTEM_CLOCK_120M); // 设置系统频率为120Mhz
FLASH_Unlock(); // 解锁 Flash
while(len--) // 根据长度
{
gFlashStatus = FLASH_ProgramWord(flash_addr, *buf++); // 按字 32bit 写入数据
if(gFlashStatus != FLASH_COMPLETE) // 反复确认操作是否成功
{
return_state = 1;
break;
}
flash_addr += 4; // 地址自增
}
FLASH_Lock(); // 锁定 Flash
//clock_reset(); // 复位时钟
//clock_set_freq(system_clock); // 设置回原来的系统频率
interrupt_global_enable(primask);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 从指定 FLASH 的扇区的指定页码读取数据到缓冲区
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 返回参数 void
// 使用示例 flash_read_page_to_buffer(63, 3);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void flash_read_page_to_buffer (uint32 sector_num, uint32 page_num)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
uint16 temp_loop;
uint32 flash_addr = ((FLASH_BASE_ADDR + FLASH_SECTION_SIZE*sector_num + FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
for(temp_loop = 0; temp_loop < FLASH_DATA_BUFFER_SIZE; temp_loop++) // 根据指定长度读取
{
flash_union_buffer[temp_loop].uint32_type = *(__IO uint32*)(flash_addr+temp_loop*4); // 循环读取 Flash 的值
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 向指定 FLASH 的扇区的指定页码写入缓冲区的数据
// 参数说明 sector_num 需要写入的扇区编号 参数范围 <0 - 63>
// 参数说明 page_num 当前扇区页的编号 参数范围 <0 - 3>
// 返回参数 uint8 1-表示失败 0-表示成功
// 使用示例 flash_write_page_from_buffer(63, 3);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 flash_write_page_from_buffer (uint32 sector_num, uint32 page_num)
{
zf_assert(sector_num <= FLASH_MAX_SECTION_INDEX); // 参数范围 0-63
zf_assert(page_num <= FLASH_MAX_PAGE_INDEX); // 参数范围 0-3
uint8 return_state = 0;
static volatile FLASH_Status gFlashStatus = FLASH_COMPLETE;
uint32 flash_addr = 0;
uint16 len = 0;
flash_addr = ((FLASH_BASE_ADDR+FLASH_SECTION_SIZE*sector_num+FLASH_PAGE_SIZE*page_num)); // 提取当前 Flash 地址
if(flash_check(sector_num, page_num)) // 判断是否有数据 这里是冗余的保护 防止有人没擦除就写入
flash_erase_sector(sector_num, page_num); // 擦除这一页
uint32 primask = interrupt_global_disable();
//clock_reset(); // 复位时钟
//clock_set_freq(SYSTEM_CLOCK_120M); // 设置系统频率为120Mhz
FLASH_Unlock(); // 解锁 Flash
while(len < FLASH_DATA_BUFFER_SIZE) // 根据长度
{
gFlashStatus = FLASH_ProgramWord(flash_addr, flash_union_buffer[len].uint32_type); // 按字 32bit 写入数据
if(gFlashStatus != FLASH_COMPLETE) // 反复确认操作是否成功
{
return_state = 1;
break;
}
len++; // 长度自增
flash_addr += 4; // 地址自增
}
FLASH_Lock(); // 锁定 Flash
//clock_reset(); // 复位时钟
//clock_set_freq(system_clock); // 设置回原来的系统频率
interrupt_global_enable(primask);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 清空数据缓冲区
// 参数说明 void
// 返回参数 void
// 使用示例 flash_buffer_clear();
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void flash_buffer_clear (void)
{
memset(flash_union_buffer, 0xFF, FLASH_PAGE_SIZE);
}

View File

@@ -0,0 +1,81 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_delay
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_flash_h
#define _zf_driver_flash_h
#include "ch32v30x.h"
#include "ch32v30x_flash.h"
#include "zf_common_typedef.h"
#define FLASH_BASE_ADDR (0x08000000) // FALSH首地址
#define FLASH_MAX_PAGE_INDEX (3)
#define FLASH_MAX_SECTION_INDEX (63)
#define FLASH_PAGE_SIZE (0x00000400) // 1K byte
#define FLASH_SECTION_SIZE (FLASH_PAGE_SIZE*4) // 4K byte
#define FLASH_OPERATION_TIME_OUT 0x0FFF
#define FLASH_DATA_BUFFER_SIZE (FLASH_PAGE_SIZE/sizeof(flash_data_union)) // 自动计算每个页能够存下多少个数据
typedef union // 固定的数据缓冲单元格式
{
float float_type; // float 类型
uint32 uint32_type; // uint32 类型
int32 int32_type; // int32 类型
uint16 uint16_type; // uint16 类型
int16 int16_type; // int16 类型
uint8 uint8_type; // uint8 类型
int8 int8_type; // int8 类型
}flash_data_union; // 所有类型数据共用同一个 32bit 地址
/*
本开源库使用的是64K RAM+ 256KFLASH
flash部分 一共64个扇区一个扇区4K。
*/
extern flash_data_union flash_union_buffer[FLASH_DATA_BUFFER_SIZE];
uint8 flash_check (uint32 sector_num, uint32 page_num);
uint8 flash_erase_sector (uint32 sector_num, uint32 page_num);
void flash_read_page (uint32 sector_num, uint32 page_num, uint32 *buf, uint16 len);
uint8 flash_write_page (uint32 sector_num, uint32 page_num, const uint32 *buf, uint16 len);
void flash_read_page_to_buffer (uint32 sector_num, uint32 page_num);
uint8 flash_write_page_from_buffer (uint32 sector_num, uint32 page_num);
void flash_buffer_clear (void);
#endif

View File

@@ -0,0 +1,158 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_gpio
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
GPIO_TypeDef *gpio_group[5] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 GPIO输出设置
// 参数说明 pin 引脚号选择的引脚 (可选择范围由 common.h 内GPIO_PIN_enum枚举值确定)
// 参数说明 dat 引脚的电平状态,输出时有效 0低电平 1高电平
// 返回参数 void
// 使用示例 gpio_set_level(D0, 0);//D0输出低电平
//-------------------------------------------------------------------------------------------------------------------
void gpio_set_level(gpio_pin_enum pin, uint8 dat)
{
if(dat)
{
gpio_high(pin); // 输出高电平
}
else
{
gpio_low(pin); // 输出低电平
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 GPIO状态获取
// 参数说明 pin 选择的引脚 (可选择范围由 common.h 内GPIO_PIN_enum枚举值确定)
// 返回参数 uint8 0低电平 1高电平
// 使用示例 uint8 status = gpio_get_level(D0);//获取D0引脚电平
//-------------------------------------------------------------------------------------------------------------------
uint8 gpio_get_level(gpio_pin_enum pin)
{
return ((gpio_group[(pin & 0xE0) >> 5]->INDR & (((uint16)0x0001) << (pin & 0x1F))) ? 1 : 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 GPIO 翻转
// 参数说明 pin 选择的引脚 (可选择范围由 common.h 内GPIO_PIN_enum枚举值确定)
// 返回参数 void
// 使用示例 gpio_toggle_level(D5);//D5引脚电平翻转
//-------------------------------------------------------------------------------------------------------------------
void gpio_toggle_level(gpio_pin_enum pin)
{
uint8 io_group = (pin & 0xE0) >> 5;
uint8 io_pin = pin & 0x1F;
((gpio_group[io_group]))->OUTDR ^= (uint16)(1 << io_pin);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 gpio 方向设置
// 参数说明 pin 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 参数说明 dir 引脚的方向 输出GPO 输入GPI
// 参数说明 mode 引脚的模式 (可选择范围由 zf_driver_gpio.h 内 gpio_mode_enum 枚举值确定)
// 返回参数 void
// 使用示例 gpio_set_dir(D5, GPI, GPI_PULL_UP); // 设置 D5 为上拉输入
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void gpio_set_dir (gpio_pin_enum pin, gpio_dir_enum dir, gpio_mode_enum mode)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
uint8 io_group = (pin & 0xE0) >> 5;
uint8 io_pin = pin & 0x1F;
// 设置引脚号
GPIO_InitStructure.GPIO_Pin = (uint16)(1 << io_pin);
// 只有输出需要设置速度
if(GPO == dir)
{
if((uint16)mode >> 8 == 0) GPIO_InitStructure.GPIO_Speed = (GPIOSpeed_TypeDef)(GPIO_Speed_50MHz); // 防止没有填写这个参数,默认设置50Mhz
else GPIO_InitStructure.GPIO_Speed = (gpio_speed_enum)((uint16)mode >> 8); // 已经填写了该参数。根据值来设置
}
// 设置模式
GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)((uint16)mode & 0xFF);
GPIO_Init(gpio_group[io_group], &GPIO_InitStructure);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 GPIO初始化
// 参数说明 pin 选择的引脚 (可选择范围由 common.h 内GPIO_PIN_enum枚举值确定)
// 参数说明 dir 引脚的方向 输出GPO 输入GPI
// 参数说明 dat 引脚初始化时设置的电平状态,输出时有效 0低电平 1高电平
// 参数说明 pinconf 引脚配置可设置参数由zf_gpio.h文件内GPIOSPEED_enum与GPIOMODE_enum枚举值确定多个条件使用 | 相或)
// 返回参数 void
// 使用示例 gpio_init(D0, GPO, 1, GPIO_PIN_CONFIG);//D0初始化为GPIO功能、输出模式、输出高电平、速度100MHZ 推挽输出
//-------------------------------------------------------------------------------------------------------------------
void gpio_init (gpio_pin_enum pin, gpio_dir_enum dir, const uint8 dat, gpio_mode_enum mode)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
uint8 io_group = (pin & 0xE0) >> 5;
uint8 io_pin = pin & 0x1F;
// GPIO总线使能
if(0 == io_group) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if(1 == io_group) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
else if(2 == io_group) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
else if(3 == io_group) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
else if(4 == io_group) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
// 设置引脚号
GPIO_InitStructure.GPIO_Pin = (uint16)(1 << io_pin);
// 只有输出需要设置速度
if(GPO == dir)
{
if((uint16)mode >> 8 == 0) GPIO_InitStructure.GPIO_Speed = (GPIOSpeed_TypeDef)(GPIO_Speed_50MHz); // 防止没有填写这个参数,默认设置50Mhz
else GPIO_InitStructure.GPIO_Speed = (gpio_speed_enum)((uint16)mode >> 8); // 已经填写了该参数。根据值来设置
}
// 设置模式
GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)((uint16)mode & 0xFF);
GPIO_Init(gpio_group[io_group], &GPIO_InitStructure);
// 只有输出需要设置引脚状态
if(GPO == dir)
{
GPIO_WriteBit(gpio_group[io_group], (uint16)(1 << io_pin), dat);
}
}

View File

@@ -0,0 +1,177 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_gpio
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_gpio_h
#define _zf_driver_gpio_h
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_exti.h"
#include "zf_common_typedef.h"
typedef enum // 枚举 GPIO 引脚 此枚举定义不允许用户修改
{
A0 = 0x00, A1 , A2 , A3 , A4 , A5 , A6 , A7 ,
A8 , A9 , A10, A11, A12, A13, A14, A15,
B0 = 0x20, B1 , B2 , B3 , B4 , B5 , B6 , B7 ,
B8 , B9 , B10, B11, B12, B13, B14, B15,
C0 = 0x40, C1 , C2 , C3 , C4 , C5 , C6 , C7 ,
C8 , C9 , C10, C11, C12, C13, C14, C15,
D0 = 0x60, D1 , D2 , D3 , D4 , D5 , D6 , D7 ,
D8 , D9 , D10, D11, D12, D13, D14, D15,
E0 = 0x80, E1 , E2 , E3 , E4 , E5 , E6 , E7 ,
E8 , E9 , E10, E11, E12, E13, E14, E15,
PIN_NULL = 0xFF
}gpio_pin_enum;
typedef enum
{
GPI = 0, // 定义管脚输入方向
GPO = 1, // 定义管脚输出方向
}gpio_dir_enum;
typedef enum
{
// 输入
GPI_ANAOG_IN = 0x00, // 模拟输入模式
GPI_FLOATING_IN = 0x04, // 浮空输入模式
GPI_PULL_DOWN = 0x28, // 下拉输入
GPI_PULL_UP = 0x48, // 上拉输入
// 输出
GPO_PUSH_PULL = 0x10, // 通用推挽输出模式
GPO_OPEN_DTAIN = 0x14, // 通用开漏输出模式
GPO_AF_PUSH_PULL = 0x18, // 复用功能推挽输出模式
GPO_AF_OPEN_DTAIN = 0x1C, // 复用功能开漏输出模式
}gpio_mode_enum;
// 宏定义GPIO引脚的默认配置便于初始化GPIO时快速填写参数如果需要其他参数可自行修改
#define GPIO_PIN_CONFIG (SPEED_50MHZ | GPO_PUSH_PULL)
// 宏定义GPIO中断和输入引脚的默认配置便于初始化GPIO中断时快速填写参数如果需要其他参数可自行修改
#define GPIO_INT_CONFIG (GPI_PULL_UP)
typedef enum
{
SPEED_10MHZ = (0x01 << 8),
SPEED_2MHZ = (0x02 << 8),
SPEED_50MHZ = (0x03 << 8)
}gpio_speed_enum;
typedef enum
{
GPIO_LOW = 0, // 低电平
GPIO_HIGH = 1, // 高电平
}gpio_level_enum;
extern GPIO_TypeDef *gpio_group[5];
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 获取对应 IO 的输入数据地址
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 uint32 32bit 地址
// 使用示例 gpio_idr_addr(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_idr_addr(x) (0x40040008 + (((x) & 0xFE0) >> 5) * 0x400 + (((x) & 0x1F) / 8))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 获取对应 IO 的输出数据地址
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 uint32 32bit 地址
// 使用示例 gpio_odr_addr(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_odr_addr(x) (0x4004000C + (((x) & 0xFE0) >> 5) * 0x400 + (((x) & 0x1F) / 8))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 获取对应 IO 的置位寄存器地址
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 uint32 32bit 地址
// 使用示例 gpio_bsrr_addr(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_bsrr_addr(x) (0x40040010 + (((x) & 0xFE0) >> 5) * 0x400 + (((x) & 0x1F) / 8))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 获取对应 IO 的复位寄存器地址
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 uint32 32bit 地址
// 使用示例 gpio_brr_addr(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_brr_addr(x) (0x40040014 + (((x) & 0xFE0) >> 5) * 0x400 + (((x) & 0x1F) / 8))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 对应 IO 复位为低电平
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 void
// 使用示例 gpio_low(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_low(x) ((GPIO_TypeDef*)gpio_group[(x>>5)])->BCR = (uint16)(1 << (x & 0x0F))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 对应 IO 置位为高电平
// 参数说明 x 选择的引脚 (可选择范围由 zf_driver_gpio.h 内 gpio_pin_enum 枚举值确定)
// 返回参数 void
// 使用示例 gpio_high(D5);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define gpio_high(x) ((GPIO_TypeDef*)gpio_group[(x>>5)])->BSHR = (uint16)(1 << (x & 0x0F))
void gpio_set_level (gpio_pin_enum pin, uint8 dat);
uint8 gpio_get_level (gpio_pin_enum pin);
void gpio_toggle_level (gpio_pin_enum pin);
void gpio_init (gpio_pin_enum pin, gpio_dir_enum dir, const uint8 dat, gpio_mode_enum mode);
#ifdef COMPATIBLE_WITH_OLDER_VERSIONS // 兼容旧版本开源库接口名称
#define gpio_set(pin, dat) (gpio_set_level((pin), (dat)))
#define gpio_get(pin) (gpio_get_level((pin)))
#define gpio_dir(pin, dir, mode) (gpio_set_dir((pin), (dir), (mode)))
#define gpio_toggle(pin) (gpio_toggle_level((pin)))
#endif
#endif

View File

@@ -0,0 +1,45 @@
/*********************************************************************************************************************
* MM32F327X-G9P Opensourec Library 即MM32F327X-G9P 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是 MM32F327X-G9P 开源库的一部分
*
* MM32F327X-G9P 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_iic
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 IAR 8.32.4 or MDK 5.37
* 适用平台 MM32F327X_G9P
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-08-10 Teternal first version
********************************************************************************************************************/
#include "zf_common_clock.h"
#include "zf_common_debug.h"
#include "zf_driver_gpio.h"
#include "zf_driver_iic.h"
// 等待后续更新
uint8 temp_update;

View File

@@ -0,0 +1,42 @@
/*********************************************************************************************************************
* MM32F327X-G9P Opensourec Library 即MM32F327X-G9P 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是 MM32F327X-G9P 开源库的一部分
*
* MM32F327X-G9P 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_iic
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 IAR 8.32.4 or MDK 5.37
* 适用平台 MM32F327X_G9P
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-08-10 Teternal first version
********************************************************************************************************************/
#ifndef _zf_driver_iic_h_
#define _zf_driver_iic_h_
#include "zf_common_typedef.h"
#endif

View File

@@ -0,0 +1,163 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_pit
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "ch32v30x_rcc.h"
#include "zf_common_clock.h"
#include "zf_common_debug.h"
#include "zf_common_interrupt.h"
#include "zf_driver_timer.h"
#include "zf_driver_pit.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 PIT 中断使能
// 参数说明 pit_n PIT 外设模块号
// 返回参数 void
// 使用示例 pit_enable(TIM1_PIT);
//-------------------------------------------------------------------------------------------------------------------
void pit_enable (pit_index_enum pit_n)
{
const uint32 irq_index[] =
{
TIM1_UP_IRQn,
TIM2_IRQn,
TIM3_IRQn,
TIM4_IRQn,
TIM5_IRQn,
TIM6_IRQn,
TIM7_IRQn,
TIM8_UP_IRQn,
TIM9_UP_IRQn,
TIM10_UP_IRQn
};
interrupt_enable(irq_index[pit_n]); // 使能中断
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 PIT 中断禁止
// 参数说明 pit_n PIT 外设模块号
// 返回参数 void
// 使用示例 pit_disable(TIM1_PIT);
//-------------------------------------------------------------------------------------------------------------------
void pit_disable (pit_index_enum pit_n)
{
const uint32 irq_index[] =
{
TIM1_UP_IRQn,
TIM2_IRQn,
TIM3_IRQn,
TIM4_IRQn,
TIM5_IRQn,
TIM6_IRQn,
TIM7_IRQn,
TIM8_UP_IRQn,
TIM9_UP_IRQn,
TIM10_UP_IRQn
};
interrupt_disable(irq_index[pit_n]); // 失能中断
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 定时器周期中断
// 参数说明 timer_ch 定时器通道
// 参数说明 us 定时周期(1-65535)
// 返回参数 void
// 备注信息 pit_init(TIMER_1, 5); 使用定时器1作为5ms一次的周期中断
//-------------------------------------------------------------------------------------------------------------------
void pit_init (pit_index_enum pit_n, uint32 period)
{
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// 这里是检查是否有重复使用定时器
// 比如初始化了 TIM1_PWM 然后又初始化成 TIM1_PIT 这种用法是不允许的
zf_assert(timer_funciton_check((timer_index_enum)pit_n, TIMER_FUNCTION_TIMER));
// 如果是这一行报错 那我就得问问你为什么周期写的是 0
zf_assert(period!=0);
uint16 freq_div = (period >> 15); // 计算预分频
uint16 period_temp = (period / (freq_div+1)); // 计算自动重装载值
timer_clock_enable(pit_n); // 使能时钟
TIM_TypeDef *tim_index = TIM1;
switch(pit_n)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
TIM_TimeBaseStructure.TIM_Period = period_temp;
TIM_TimeBaseStructure.TIM_Prescaler = freq_div; // 分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器设置为0
TIM_TimeBaseInit(tim_index, &TIM_TimeBaseStructure); // 根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(tim_index,TIM_IT_Update,ENABLE ); // 使能指定的TIM中断,允许更新中断
TIM_ClearITPendingBit(tim_index, TIM_IT_Update);
const uint32 irq_index[10] =
{
TIM1_UP_IRQn,
TIM2_IRQn,
TIM3_IRQn,
TIM4_IRQn,
TIM5_IRQn,
TIM6_IRQn,
TIM7_IRQn,
TIM8_UP_IRQn,
TIM9_UP_IRQn,
TIM10_UP_IRQn
};
interrupt_set_priority((IRQn_Type)irq_index[(uint8)pit_n], 0x03); // 设置中断优先级
interrupt_enable((IRQn_Type)irq_index[pit_n]); // 使能中断
TIM_Cmd(tim_index, ENABLE); // 使能定时器
}

View File

@@ -0,0 +1,87 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_pit
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_pit_h
#define _zf_driver_pit_h
#include "zf_common_interrupt.h"
typedef enum // 枚举 TIM通道
{
TIM1_PIT,
TIM2_PIT,
TIM3_PIT,
TIM4_PIT,
TIM5_PIT,
TIM6_PIT,
TIM7_PIT,
TIM8_PIT,
TIM9_PIT,
TIM10_PIT
}pit_index_enum;
void pit_enable (pit_index_enum pit_n);
void pit_disable (pit_index_enum pit_n);
void pit_init (pit_index_enum pit_n, uint32 period);
//====================================================宏定义函数区====================================================
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 TIM PIT 中断初始化 ms 周期
// 参数说明 pit_n 使用的 PIT 编号
// 参数说明 ms PIT 周期 ms 级别
// 返回参数 void
// 使用示例 pit_ms_init(TIM6_PIT, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define pit_ms_init(pit_n, ms) (pit_init((pit_n), (ms) * (system_clock / 1000)))
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 TIM PIT 中断初始化 us 周期
// 参数说明 pit_n 使用的 PIT 编号
// 参数说明 us PIT 周期 us 级别
// 返回参数 void
// 使用示例 pit_us_init(TIM6_PIT, 100);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
#define pit_us_init(pit_n, us) (pit_init((pit_n), (us) * (system_clock / 1000000)))
//====================================================宏定义函数区====================================================
#endif

View File

@@ -0,0 +1,266 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_pwm
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
#include "zf_driver_timer.h"
#include "zf_driver_pwm.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 PWM占空比设定
// 参数说明 pwmch PWM通道号及引脚
// 参数说明 duty PWM占空比
// 返回参数 void
// 使用示例 pwm_set_duty(TIM10_PWM_CH4_C15, 5000); //定时器10 通道4 使用引脚C15 占空比为百分之 5000/PWM_DUTY_MAX*100
// PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_set_duty(pwm_channel_enum pin, uint32 duty)
{
// 如果是这一行报错 那你得去看看最大占空比是限定的多少 占空比写入错误
zf_assert(PWM_DUTY_MAX >= duty); // 占空比写入错误
TIM_TypeDef *tim_index = TIM1;
switch((pin & 0xF0000) >> 16) // 获取TIM编号
{
case 0: tim_index = TIM1; break;
case 1: tim_index = TIM2; break;
case 2: tim_index = TIM3; break;
case 3: tim_index = TIM4; break;
case 4: tim_index = TIM5; break;
case 7: tim_index = TIM8; break;
case 8: tim_index = TIM9; break;
case 9: tim_index = TIM10; break;
}
uint16 match_temp;
uint16 period_temp;
period_temp = tim_index->ATRLR; // 获取定时器的周期值
match_temp = period_temp * duty / PWM_DUTY_MAX; // 占空比
if(((pin>>8) & 0x03) == 0x00) // 通道选择
{
tim_index->CH1CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x01) // 通道选择
{
tim_index->CH2CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x02) // 通道选择
{
tim_index->CH3CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x03) // 通道选择
{
tim_index->CH4CVR = match_temp;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 PWM频率设定
// 参数说明 pwmch PWM通道号及引脚
// 参数说明 freq PWM频率
// 参数说明 duty PWM占空比
// 返回参数 void
// 使用示例 pwm_set_freq(PWM1_CH1_A8, 60, 5000); //使用引脚A8 输出PWM频率60HZ 占空比为百分之 5000/PWM_DUTY_MAX*100
// PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_set_freq(pwm_channel_enum pin, uint32 freq, uint32 duty)
{
uint16 period_temp = 0; // 周期值
uint16 freq_div = 0; // 分频值
uint16 match_temp;
freq_div = (uint16)((system_clock / freq) >> 16); // 计算多少分频
period_temp = (uint16)(system_clock/(freq*(freq_div + 1))); // 计算周期
// 获取TIM编号
TIM_TypeDef *tim_index = TIM1;
switch((pin & 0xF0000) >> 16)
{
case 0: tim_index = TIM1; break;
case 1: tim_index = TIM2; break;
case 2: tim_index = TIM3; break;
case 3: tim_index = TIM4; break;
case 4: tim_index = TIM5; break;
case 7: tim_index = TIM8; break;
case 8: tim_index = TIM9; break;
case 9: tim_index = TIM10; break;
}
tim_index->ATRLR = period_temp - 1 ;
tim_index->PSC = freq_div;
match_temp = period_temp * duty / PWM_DUTY_MAX; // 占空比
if(((pin>>8) & 0x03) == 0x00) // 通道选择
{
tim_index->CH1CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x01) // 通道选择
{
tim_index->CH2CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x02) // 通道选择
{
tim_index->CH3CVR = match_temp;
}
else if(((pin>>8) & 0x03) == 0x03) // 通道选择
{
tim_index->CH4CVR = match_temp;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 PWM初始化
// 参数说明 pwmch PWM通道号及引脚
// 参数说明 freq PWM频率
// 参数说明 duty PWM占空比
// 返回参数 void
// 使用示例 pwm_init(PWM1_CH1_A8, 50, 5000); //初始化PWM1 通道1 使用引脚A8 输出PWM频率50HZ 占空比为百分之 5000/PWM_DUTY_MAX*100
// PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_init(pwm_channel_enum pin, uint32 freq, uint32 duty)
{
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// 这里是检查是否有重复使用定时器
// 比如初始化了 TIM1_PIT 然后又初始化成 TIM1_PWM 这种用法是不允许的
zf_assert(timer_funciton_check((timer_index_enum)(pin>>16), TIMER_FUNCTION_PWM));
// 如果是这一行报错 那你得去看看最大占空比是限定的多少 占空比写入错误
zf_assert(PWM_DUTY_MAX >= duty);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
TIM_OCInitTypeDef TIM_OCInitStructure = {0};
uint16 match_temp; // 占空比值
uint16 period_temp; // 周期值
uint16 freq_div = 0; // 分频值
timer_clock_enable((pin & 0xF0000) >> 16); // 定时器时钟使能
gpio_init((gpio_pin_enum)(pin & 0xFF), GPO, 0, GPO_AF_PUSH_PULL | SPEED_50MHZ); // 初始化引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO复用功能模块时钟
// 获取TIM编号
TIM_TypeDef *tim_index = TIM1;
switch((pin & 0xF0000) >> 16)
{
case 0: tim_index = TIM1; break;
case 1: tim_index = TIM2; break;
case 2: tim_index = TIM3; break;
case 3: tim_index = TIM4; break;
case 4: tim_index = TIM5; break;
case 7: tim_index = TIM8; break;
case 8: tim_index = TIM9; break;
case 9: tim_index = TIM10; break;
}
// 开启复用功能
if((pin >> 12) == 0x03) GPIO_PinRemapConfig(GPIO_FullRemap_TIM1, ENABLE);
else if((pin >> 12) == 0x11) GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
else if((pin >> 12) == 0x12) GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);
else if((pin >> 12) == 0x13) GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
else if((pin >> 12) == 0x22) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
else if((pin >> 12) == 0x23) GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
else if((pin >> 12) == 0x31) GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
else if((pin >> 12) == 0x71) GPIO_PinRemapConfig(GPIO_Remap_TIM8, ENABLE);
else if((pin >> 12) == 0x83) GPIO_PinRemapConfig(GPIO_FullRemap_TIM9, ENABLE);
else if((pin >> 12) == 0x91) GPIO_PinRemapConfig(GPIO_PartialRemap_TIM10, ENABLE);
else if((pin >> 12) == 0x93) GPIO_PinRemapConfig(GPIO_FullRemap_TIM10, ENABLE);
freq_div = (uint16)((system_clock / freq) >> 16); // 多少分频
period_temp = (uint16)(system_clock/(freq*(freq_div + 1))); // 周期
match_temp = period_temp * duty / PWM_DUTY_MAX; // 占空比
TIM_TimeBaseStructure.TIM_Period = period_temp - 1; // 设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = freq_div; // 设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(tim_index, &TIM_TimeBaseStructure); // 根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // 选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = match_temp;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 输出极性:TIM输出比较极性低
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low; // 输出极性:TIM输出比较极性低
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
if(((pin>>8) & 0x03) == 0x00) // 通道选择
{
TIM_OC1Init(tim_index, &TIM_OCInitStructure ); // 定时器通道1初始化
TIM_OC1PreloadConfig(tim_index, TIM_OCPreload_Enable); // 定时器预装载配置
TIM_OC1FastConfig(tim_index, TIM_OC1FE); // 比较捕获通道快速使能
}
else if(((pin>>8) & 0x03) == 0x01)
{
TIM_OC2Init(tim_index, &TIM_OCInitStructure );
TIM_OC2PreloadConfig(tim_index, TIM_OCPreload_Enable);
TIM_OC2FastConfig(tim_index, TIM_OC2FE);
}
else if(((pin>>8) & 0x03) == 0x02)
{
TIM_OC3Init(tim_index, &TIM_OCInitStructure );
TIM_OC3PreloadConfig(tim_index, TIM_OCPreload_Enable);
TIM_OC3FastConfig(tim_index, TIM_OC3FE);
}
else if(((pin>>8) & 0x03) == 0x03)
{
TIM_OC4Init(tim_index, &TIM_OCInitStructure );
TIM_OC4PreloadConfig(tim_index, TIM_OCPreload_Enable);
TIM_OC4FastConfig(tim_index, TIM_OC4FE);
}
TIM_CtrlPWMOutputs(tim_index, ENABLE ); // 通道PWM输出使能
TIM_Cmd(tim_index, ENABLE); // 定时器使能
//TIM_ARRPreloadConfig( TIM1, ENABLE );
}

View File

@@ -0,0 +1,213 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_PWM_MAP
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_PWM_MAP_h
#define _zf_driver_PWM_MAP_h
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_tim.h"
#include "zf_common_debug.h"
typedef enum
{
// MAP0 默认映射
// MAP1 重映射
// MAP2 部分映射
// MAP3 完全映射
// 同一个PWMP模块不同通道只能输出相同频率的PWM占空比可设置不同
// 例如PWM1_PWM_MAP_CH1_PA8与PWM1_PWM_MAP_CH3_PA10属于同一个模块频率只能一样但是占空比可以不一样
//----------------定时器1----------------
// 例如PWM1_PWM_MAP_CH2_PA9与PWM1_PWM_MAP_CH1N_PB13不能一起使用。
// 只允许TIM1_PWM_MAP0_CH1_A8 和 TIM1_PWM_MAP0_CH2_A9和 TIM1_PWM_MAP0_CH3_A10 和 TIM1_PWM_MAP0_CH4_A11 同组映射引脚一起使用
// 以下为TIM1的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM1_PWM_MAP0_CH1_A8 = 0x00000 | A8 , // 0x 0[TIM1] 0[MAP0] 0[CH1] 08[A8 ]
TIM1_PWM_MAP0_CH2_A9 = 0x00100 | A9 , // 0x 0[TIM1] 0[MAP0] 1[CH2] 09[A9 ]
TIM1_PWM_MAP0_CH3_A10 = 0x00200 | A10, // 0x 0[TIM1] 0[MAP0] 2[CH3] 0A[A10]
TIM1_PWM_MAP0_CH4_A11 = 0x00300 | A11, // 0x 0[TIM1] 0[MAP0] 3[CH4] 0B[A11]
// 以下为TIM1的PWM的一组映射引脚不允许映射引脚混用。
// 完全映射
TIM1_PWM_MAP3_CH1_E9 = 0x03000 | E9 , // 0x 0[TIM1] 3[MAP3] 0[CH1] 69[E9 ]
TIM1_PWM_MAP3_CH2_E11 = 0x03100 | E11, // 0x 0[TIM1] 3[MAP3] 1[CH2] 6B[E11]
TIM1_PWM_MAP3_CH3_E13 = 0x03200 | E13, // 0x 0[TIM1] 3[MAP3] 2[CH3] 6D[E13]
TIM1_PWM_MAP3_CH4_E14 = 0x03300 | E14, // 0x 0[TIM1] 3[MAP3] 3[CH4] 6E[E14]
//----------------定时器2----------------
// 以下为TIM2的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM2_PWM_MAP0_CH1_A0 = 0x10000 | A0,
TIM2_PWM_MAP0_CH2_A1 = 0x10100 | A1,
TIM2_PWM_MAP0_CH3_A2 = 0x10200 | A2,
TIM2_PWM_MAP0_CH4_A3 = 0x10300 | A3,
// 以下为TIM2的PWM的一组映射引脚不允许映射引脚混用。
// 重映射
TIM2_PWM_MAP1_CH1_A15 = 0x11000 | A15,
TIM2_PWM_MAP1_CH2_B3 = 0x11100 | B3 ,
TIM2_PWM_MAP1_CH3_A2 = 0x11200 | A2 ,
TIM2_PWM_MAP1_CH4_A3 = 0x11300 | A3 ,
// 以下为TIM2的PWM的一组映射引脚不允许映射引脚混用。
// 部分映射
TIM2_PWM_MAP2_CH1_A0 = 0x12000 | A0 ,
TIM2_PWM_MAP2_CH2_A1 = 0x12100 | A1 ,
TIM2_PWM_MAP2_CH3_B10 = 0x12200 | B10, // 下载器默认串口,如果需要使用,则需要屏蔽默认串口初始化
TIM2_PWM_MAP2_CH4_B11 = 0x12300 | B11, // 下载器默认串口,如果需要使用,则需要屏蔽默认串口初始化
// 以下为TIM2的PWM的一组映射引脚不允许映射引脚混用。
// 完全映射
TIM2_PWM_MAP3_CH1_A15 = 0x13000 | A15,
TIM2_PWM_MAP3_CH2_B3 = 0x13100 | B3 ,
TIM2_PWM_MAP3_CH3_B10 = 0x13200 | B10, // 下载器默认串口,如果需要使用,则需要屏蔽默认串口初始化
TIM2_PWM_MAP3_CH4_B11 = 0x13300 | B11, // 下载器默认串口,如果需要使用,则需要屏蔽默认串口初始化
//----------------定时器3----------------
// 以下为TIM3的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM3_PWM_MAP0_CH1_A6 = 0x20000 | A6,
TIM3_PWM_MAP0_CH2_A7 = 0x20100 | A7,
TIM3_PWM_MAP0_CH3_B0 = 0x20200 | B0,
TIM3_PWM_MAP0_CH4_B1 = 0x20300 | B1,
// 以下为TIM3的PWM的一组映射引脚不允许映射引脚混用。
// 部分映射
TIM3_PWM_MAP2_CH1_B4 = 0x22000 | B4,
TIM3_PWM_MAP2_CH2_B5 = 0x22100 | B5,
TIM3_PWM_MAP2_CH3_B0 = 0x22200 | B0,
TIM3_PWM_MAP2_CH4_B1 = 0x22300 | B1,
// 以下为TIM3的PWM的一组映射引脚不允许映射引脚混用。
// 完全映射
TIM3_PWM_MAP3_CH1_C6 = 0x23000 | C6,
TIM3_PWM_MAP3_CH2_C7 = 0x23100 | C7,
TIM3_PWM_MAP3_CH3_C8 = 0x23200 | C8,
TIM3_PWM_MAP3_CH4_C9 = 0x23300 | C9,
//----------------定时器4----------------
// 以下为TIM4的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM4_PWM_MAP0_CH1_B6 = 0x30000 | B6,
TIM4_PWM_MAP0_CH2_B7 = 0x30100 | B7,
TIM4_PWM_MAP0_CH3_B8 = 0x30200 | B8,
TIM4_PWM_MAP0_CH4_B9 = 0x30300 | B9,
// 以下为TIM4的PWM的一组映射引脚不允许映射引脚混用。
//重映射
TIM4_PWM_MAP1_CH1_D12 = 0x31000 | D12,
TIM4_PWM_MAP1_CH2_D13 = 0x31100 | D13,
TIM4_PWM_MAP1_CH3_D14 = 0x31200 | D14,
TIM4_PWM_MAP1_CH4_D15 = 0x31300 | D15,
//----------------定时器5----------------
// 以下为TIM5的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM5_PWM_MAP0_CH1_A0 = 0x40000 | A0,
TIM5_PWM_MAP0_CH2_A1 = 0x40100 | A1,
TIM5_PWM_MAP0_CH3_A2 = 0x40200 | A2,
TIM5_PWM_MAP0_CH4_A3 = 0x40300 | A3,
//----------------定时器8----------------
// 以下为TIM8的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM8_PWM_MAP0_CH1_C6 = 0x70000 | C6,
TIM8_PWM_MAP0_CH2_C7 = 0x70100 | C7,
TIM8_PWM_MAP0_CH3_C8 = 0x70200 | C8,
TIM8_PWM_MAP0_CH4_C9 = 0x70300 | C9,
// 以下为TIM8的PWM的一组映射引脚不允许映射引脚混用。
//重映射
TIM8_PWM_MAP1_CH1_B6 = 0x71000 | B6 ,
TIM8_PWM_MAP1_CH2_B7 = 0x71100 | B7 ,
TIM8_PWM_MAP1_CH3_B8 = 0x71200 | B8 ,
TIM8_PWM_MAP1_CH4_C13 = 0x71300 | C13,
//----------------定时器9----------------
// 以下为TIM9的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM9_PWM_MAP0_CH1_A2 = 0x80000 | A2,
TIM9_PWM_MAP0_CH2_A3 = 0x80100 | A3,
TIM9_PWM_MAP0_CH3_A4 = 0x80200 | A4,
TIM9_PWM_MAP0_CH4_C4 = 0x80300 | C4,
// 以下为TIM9的PWM的一组映射引脚不允许映射引脚混用。
// 完全映射
TIM9_PWM_MAP3_CH1_D9 = 0x83000 | D9 ,
TIM9_PWM_MAP3_CH2_D11 = 0x83100 | D11,
TIM9_PWM_MAP3_CH3_D13 = 0x83200 | D13,
TIM9_PWM_MAP3_CH4_D15 = 0x83300 | D15,
//----------------定时器10----------------
// 以下为TIM10的PWM的一组映射引脚不允许映射引脚混用。
// 默认映射
TIM10_PWM_MAP0_CH1_B8 = 0x90000 | B8 ,
TIM10_PWM_MAP0_CH2_B9 = 0x90100 | B9 ,
TIM10_PWM_MAP0_CH3_C3 = 0x90200 | C3 ,
TIM10_PWM_MAP0_CH4_C11= 0x90300 | C11,
// 以下为TIM10的PWM的一组映射引脚不允许映射引脚混用。
//部分映射
TIM10_PWM_MAP1_CH1_B3 = 0x91000 | B3 ,
TIM10_PWM_MAP1_CH2_B4 = 0x91100 | B4 ,
TIM10_PWM_MAP1_CH3_B5 = 0x91200 | B5 ,
TIM10_PWM_MAP1_CH4_C15= 0x91300 | C15,
// 以下为TIM10的PWM的一组映射引脚不允许映射引脚混用。
//完全映射
TIM10_PWM_MAP3_CH1_D1 = 0x93000 | D1,
TIM10_PWM_MAP3_CH2_D3 = 0x93100 | D3,
TIM10_PWM_MAP3_CH3_D5 = 0x93200 | D5,
TIM10_PWM_MAP3_CH4_D7 = 0x93300 | D7,
}pwm_channel_enum;
#define PWM_DUTY_MAX 10000
void pwm_set_duty (pwm_channel_enum pin, uint32 duty);
void pwm_set_freq (pwm_channel_enum pin, uint32 freq, uint32 duty);
void pwm_init (pwm_channel_enum pin, uint32 freq, uint32 duty);
#endif

View File

@@ -0,0 +1,711 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_soft_iic
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_common_debug.h"
#include "zf_driver_soft_iic.h"
#define SOFT_IIC_SDA_IO_SWITCH (0) // 是否需要 SDA 进行 I/O 切换 0-不需要 1-需要
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 延时
// 参数说明 delay 延时次数
// 返回参数 void
// 使用示例 soft_iic_delay(1);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
//static void soft_iic_delay (vuint32 delay)
//{
// volatile uint32 count = delay;
// while(count --);
//}
#define soft_iic_delay(x) for(uint32 i = x; i--; )
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC START 信号
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 返回参数 void
// 使用示例 soft_iic_start(soft_iic_obj);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static void soft_iic_start (soft_iic_info_struct *soft_iic_obj)
{
zf_assert(soft_iic_obj != NULL);
gpio_high(soft_iic_obj->scl_pin); // SCL 高电平
gpio_high(soft_iic_obj->sda_pin); // SDA 高电平
soft_iic_delay(soft_iic_obj->delay);
gpio_low(soft_iic_obj->sda_pin); // SDA 先拉低
soft_iic_delay(soft_iic_obj->delay);
gpio_low(soft_iic_obj->scl_pin); // SCL 再拉低
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC STOP 信号
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 返回参数 void
// 使用示例 soft_iic_stop(soft_iic_obj);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static void soft_iic_stop (soft_iic_info_struct *soft_iic_obj)
{
zf_assert(soft_iic_obj != NULL);
gpio_low(soft_iic_obj->sda_pin); // SDA 低电平
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->scl_pin); // SCL 先拉高
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->sda_pin); // SDA 再拉高
soft_iic_delay(soft_iic_obj->delay);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 发送 ACK/NAKC 信号 内部调用
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 ack ACK 电平
// 返回参数 void
// 使用示例 soft_iic_send_ack(soft_iic_obj, 1);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static void soft_iic_send_ack (soft_iic_info_struct *soft_iic_obj, uint8 ack)
{
zf_assert(soft_iic_obj != NULL);
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
if(ack)
{
gpio_high(soft_iic_obj->sda_pin); // SDA 拉高
}
else
{
gpio_low(soft_iic_obj->sda_pin); // SDA 拉低
}
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->scl_pin); // SCL 拉高
soft_iic_delay(soft_iic_obj->delay);
gpio_low(soft_iic_obj->scl_pin); // SCL 拉低
gpio_high(soft_iic_obj->sda_pin); // SDA 拉高
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 获取 ACK/NAKC 信号
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 返回参数 uint8 ACK 状态
// 使用示例 soft_iic_wait_ack(soft_iic_obj);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static uint8 soft_iic_wait_ack (soft_iic_info_struct *soft_iic_obj)
{
zf_assert(soft_iic_obj != NULL);
uint8 temp = 0;
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
gpio_high(soft_iic_obj->sda_pin); // SDA 高电平 释放 SDA
#if SOFT_IIC_SDA_IO_SWITCH
gpio_set_dir(soft_iic_obj->sda_pin, GPI, GPI_FLOATING_IN);
#endif
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->scl_pin); // SCL 高电平
soft_iic_delay(soft_iic_obj->delay);
if(gpio_get_level((gpio_pin_enum)soft_iic_obj->sda_pin))
{
temp = 1;
}
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
#if SOFT_IIC_SDA_IO_SWITCH
gpio_set_dir(soft_iic_obj->sda_pin, GPO, GPO_OPEN_DTAIN);
#endif
soft_iic_delay(soft_iic_obj->delay);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 发送 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 data 数据
// 返回参数 uint8 ACK 状态
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static uint8 soft_iic_send_data (soft_iic_info_struct *soft_iic_obj, const uint8 data)
{
zf_assert(soft_iic_obj != NULL);
uint8 temp = 0x80;
while(temp)
{
// gpio_set_level(soft_iic_obj->sda_pin, data & temp);
((data & temp) ? (gpio_high(soft_iic_obj->sda_pin)) : (gpio_low(soft_iic_obj->sda_pin)));
temp >>= 1;
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->scl_pin); // SCL 拉高
soft_iic_delay(soft_iic_obj->delay);
gpio_low(soft_iic_obj->scl_pin); // SCL 拉低
}
return ((soft_iic_wait_ack(soft_iic_obj) == 1) ? 0 : 1 );
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 读取 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 ack ACK 或 NACK
// 返回参数 uint8 数据
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static uint8 soft_iic_read_data (soft_iic_info_struct *soft_iic_obj, uint8 ack)
{
zf_assert(soft_iic_obj != NULL);
uint8 data = 0x00;
uint8 temp = 8;
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->sda_pin); // SDA 高电平 释放 SDA
#if SOFT_IIC_SDA_IO_SWITCH
gpio_set_dir(soft_iic_obj->sda_pin, GPI, GPI_FLOATING_IN);
#endif
while(temp --)
{
gpio_low(soft_iic_obj->scl_pin); // SCL 拉低
soft_iic_delay(soft_iic_obj->delay);
gpio_high(soft_iic_obj->scl_pin); // SCL 拉高
soft_iic_delay(soft_iic_obj->delay);
data = ((data << 1) | gpio_get_level((gpio_pin_enum)soft_iic_obj->sda_pin));
}
gpio_low(soft_iic_obj->scl_pin); // SCL 低电平
#if SOFT_IIC_SDA_IO_SWITCH
gpio_set_dir(soft_iic_obj->sda_pin, GPO, GPO_OPEN_DTAIN);
#endif
soft_iic_delay(soft_iic_obj->delay);
soft_iic_send_ack(soft_iic_obj, ack);
return data;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口写 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 data 要写入的数据
// 返回参数 void
// 使用示例 soft_iic_write_8bit_register(soft_iic_obj, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_8bit (soft_iic_info_struct *soft_iic_obj, const uint8 data)
{
zf_assert(soft_iic_obj != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, data);
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口写 8bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_iic_write_8bit_array(soft_iic_obj, data, 6);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_8bit_array (soft_iic_info_struct *soft_iic_obj, const uint8 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
while(len --)
{
soft_iic_send_data(soft_iic_obj, *data ++);
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口器写 16bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 data 要写入的数据
// 返回参数 void
// 使用示例 soft_iic_write_16bit(soft_iic_obj, 0x0101);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_16bit (soft_iic_info_struct *soft_iic_obj, const uint16 data)
{
zf_assert(soft_iic_obj != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, (uint8)((data & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(data & 0x00FF));
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口写 16bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_iic_write_16bit_array(soft_iic_obj, data, 6);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_16bit_array (soft_iic_info_struct *soft_iic_obj, const uint16 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
while(len --)
{
soft_iic_send_data(soft_iic_obj, (uint8)((*data & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(*data ++ & 0x00FF));
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口向传感器寄存器写 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 data 要写入的数据
// 返回参数 void
// 使用示例 soft_iic_write_8bit_register(soft_iic_obj, 0x01, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_8bit_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, const uint8 data)
{
zf_assert(soft_iic_obj != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
soft_iic_send_data(soft_iic_obj, data);
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口向传感器寄存器写 8bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_iic_write_8bit_registers(soft_iic_obj, 0x01, data, 6);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_8bit_registers (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, const uint8 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
while(len --)
{
soft_iic_send_data(soft_iic_obj, *data ++);
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口向传感器寄存器写 16bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 data 要写入的数据
// 返回参数 void
// 使用示例 soft_iic_write_16bit_register(soft_iic_obj, 0x0101, 0x0101);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_16bit_register (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, const uint16 data)
{
zf_assert(soft_iic_obj != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, (uint8)((register_name & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(register_name & 0x00FF));
soft_iic_send_data(soft_iic_obj, (uint8)((data & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(data & 0x00FF));
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口向传感器寄存器写 16bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_iic_write_16bit_registers(soft_iic_obj, 0x0101, data, 6);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_write_16bit_registers (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, const uint16 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, (uint8)((register_name & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(register_name & 0x00FF));
while(len--)
{
soft_iic_send_data(soft_iic_obj, (uint8)((*data & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(*data ++ & 0x00FF));
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口读取 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 返回参数 uint8 返回读取的 8bit 数据
// 使用示例 soft_iic_read_8bit(soft_iic_obj);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 soft_iic_read_8bit (soft_iic_info_struct *soft_iic_obj)
{
zf_assert(soft_iic_obj != NULL);
uint8 temp = 0;
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
temp = soft_iic_read_data(soft_iic_obj, 1);
soft_iic_stop(soft_iic_obj);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口从传感器寄存器读取 8bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 *data 要读取的数据的缓冲区指针
// 参数说明 len 要读取的数据长度
// 返回参数 void
// 使用示例 soft_iic_read_8bit_array(soft_iic_obj, data, 8);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_read_8bit_array (soft_iic_info_struct *soft_iic_obj, uint8 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(len --)
{
*data ++ = soft_iic_read_data(soft_iic_obj, len == 0);
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口读取 16bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 返回参数 uint16 返回读取的 16bit 数据
// 使用示例 soft_iic_read_16bit(soft_iic_obj);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint16 soft_iic_read_16bit (soft_iic_info_struct *soft_iic_obj)
{
zf_assert(soft_iic_obj != NULL);
uint16 temp = 0;
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
temp = soft_iic_read_data(soft_iic_obj, 0);
temp = ((temp << 8)| soft_iic_read_data(soft_iic_obj, 1));
soft_iic_stop(soft_iic_obj);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口读取 16bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 *data 要读取的数据的缓冲区指针
// 参数说明 len 要读取的数据长度
// 返回参数 void
// 使用示例 soft_iic_read_16bit_array(soft_iic_obj, data, 8);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_read_16bit_array (soft_iic_info_struct *soft_iic_obj, uint16 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(len --)
{
*data = soft_iic_read_data(soft_iic_obj, 0);
*data = ((*data << 8)| soft_iic_read_data(soft_iic_obj, len == 0));
data ++;
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口从传感器寄存器读取 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 返回参数 uint8 返回读取的 8bit 数据
// 使用示例 soft_iic_read_8bit_register(soft_iic_obj, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 soft_iic_read_8bit_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name)
{
zf_assert(soft_iic_obj != NULL);
uint8 temp = 0;
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
temp = soft_iic_read_data(soft_iic_obj, 1);
soft_iic_stop(soft_iic_obj);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口从传感器寄存器读取 8bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 *data 要读取的数据的缓冲区指针
// 参数说明 len 要读取的数据长度
// 返回参数 void
// 使用示例 soft_iic_read_8bit_registers(soft_iic_obj, 0x01, data, 8);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_read_8bit_registers (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, uint8 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(len --)
{
*data ++ = soft_iic_read_data(soft_iic_obj, len == 0);
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口从传感器寄存器读取 16bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 返回参数 uint16 返回读取的 16bit 数据
// 使用示例 soft_iic_read_16bit_register(soft_iic_obj, 0x0101);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint16 soft_iic_read_16bit_register (soft_iic_info_struct *soft_iic_obj, const uint16 register_name)
{
zf_assert(soft_iic_obj != NULL);
uint16 temp = 0;
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, (uint8)((register_name & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(register_name & 0x00FF));
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
temp = soft_iic_read_data(soft_iic_obj, 0);
temp = ((temp << 8)| soft_iic_read_data(soft_iic_obj, 1));
soft_iic_stop(soft_iic_obj);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口从传感器寄存器读取 16bit 数组
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 *data 要读取的数据的缓冲区指针
// 参数说明 len 要读取的数据长度
// 返回参数 void
// 使用示例 soft_iic_read_16bit_registers(soft_iic_obj, 0x0101, data, 8);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_read_16bit_registers (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, uint16 *data, uint32 len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, (uint8)((register_name & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(register_name & 0x00FF));
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(len --)
{
*data = soft_iic_read_data(soft_iic_obj, 0);
*data = ((*data << 8)| soft_iic_read_data(soft_iic_obj, len == 0));
data ++;
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口传输 8bit 数组 先写后读取
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 *write_data 发送数据存放缓冲区
// 参数说明 write_len 发送缓冲区长度
// 参数说明 *read_data 读取数据存放缓冲区
// 参数说明 read_len 读取缓冲区长度
// 返回参数 void
// 使用示例 iic_transfer_8bit_array(IIC_1, addr, data, 64, data, 64);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_transfer_8bit_array (soft_iic_info_struct *soft_iic_obj, const uint8 *write_data, uint32 write_len, uint8 *read_data, uint32 read_len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(write_data != NULL);
zf_assert(read_data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
while(write_len --)
{
soft_iic_send_data(soft_iic_obj, *write_data ++);
}
if(read_len)
{
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(read_len --)
{
*read_data ++ = soft_iic_read_data(soft_iic_obj, read_len == 0);
}
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口传输 16bit 数组 先写后读取
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 *write_data 发送数据存放缓冲区
// 参数说明 write_len 发送缓冲区长度
// 参数说明 *read_data 读取数据存放缓冲区
// 参数说明 read_len 读取缓冲区长度
// 返回参数 void
// 使用示例 iic_transfer_16bit_array(IIC_1, addr, data, 64, data, 64);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_transfer_16bit_array (soft_iic_info_struct *soft_iic_obj, const uint16 *write_data, uint32 write_len, uint16 *read_data, uint32 read_len)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(write_data != NULL);
zf_assert(read_data != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
while(write_len--)
{
soft_iic_send_data(soft_iic_obj, (uint8)((*write_data & 0xFF00) >> 8));
soft_iic_send_data(soft_iic_obj, (uint8)(*write_data ++ & 0x00FF));
}
if(read_len)
{
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
while(read_len --)
{
*read_data = soft_iic_read_data(soft_iic_obj, 0);
*read_data = ((*read_data << 8)| soft_iic_read_data(soft_iic_obj, read_len == 0));
read_data ++;
}
}
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口 SCCB 模式向传感器寄存器写 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 参数说明 data 要写入的数据
// 返回参数 void
// 使用示例 soft_iic_sccb_write_register(soft_iic_obj, 0x01, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_sccb_write_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, uint8 data)
{
zf_assert(soft_iic_obj != NULL);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
soft_iic_send_data(soft_iic_obj, data);
soft_iic_stop(soft_iic_obj);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口 SCCB 模式从传感器寄存器读取 8bit 数据
// 参数说明 *soft_iic_obj 软件 IIC 指定信息 可以参照 zf_driver_soft_iic.h 里的格式看看
// 参数说明 register_name 传感器的寄存器地址
// 返回参数 uint8 返回读取的 8bit 数据
// 使用示例 soft_iic_sccb_read_register(soft_iic_obj, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 soft_iic_sccb_read_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name)
{
zf_assert(soft_iic_obj != NULL);
uint8 temp = 0;
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1);
soft_iic_send_data(soft_iic_obj, register_name);
soft_iic_stop(soft_iic_obj);
soft_iic_start(soft_iic_obj);
soft_iic_send_data(soft_iic_obj, soft_iic_obj->addr << 1 | 0x01);
temp = soft_iic_read_data(soft_iic_obj, 1);
soft_iic_stop(soft_iic_obj);
return temp;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 IIC 接口初始化 默认 MASTER 模式 不提供 SLAVE 模式
// 参数说明 *soft_iic_obj 软件 IIC 指定信息存放结构体的指针
// 参数说明 addr 软件 IIC 地址 这里需要注意 标准七位地址 最高位忽略 写入时请务必确认无误
// 参数说明 delay 软件 IIC 延时 就是时钟高电平时间 越短 IIC 速率越高
// 参数说明 scl_pin 软件 IIC 时钟引脚 参照 zf_driver_gpio.h 内 gpio_pin_enum 枚举体定义
// 参数说明 sda_pin 软件 IIC 数据引脚 参照 zf_driver_gpio.h 内 gpio_pin_enum 枚举体定义
// 返回参数 void
// 使用示例 soft_iic_init(&soft_iic_obj, addr, 100, B6, B7);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_iic_init (soft_iic_info_struct *soft_iic_obj, uint8 addr, uint32 delay, gpio_pin_enum scl_pin, gpio_pin_enum sda_pin)
{
zf_assert(soft_iic_obj != NULL);
zf_assert(scl_pin != sda_pin); // 醒醒! scl_pin 与 sda_pin 怎么能填同一个引脚?
soft_iic_obj->scl_pin = scl_pin;
soft_iic_obj->sda_pin = sda_pin;
soft_iic_obj->addr = addr;
soft_iic_obj->delay = delay;
gpio_init(scl_pin, GPO, GPIO_HIGH, GPO_PUSH_PULL); // 提取对应IO索引 AF功能编码
gpio_init(sda_pin, GPO, GPIO_HIGH, GPO_OPEN_DTAIN); // 提取对应IO索引 AF功能编码
}

View File

@@ -0,0 +1,83 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_soft_iic
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_soft_iic_h_
#define _zf_driver_soft_iic_h_
#include "zf_driver_gpio.h"
typedef struct
{
gpio_pin_enum scl_pin; // 用于记录对应的引脚编号
gpio_pin_enum sda_pin; // 用于记录对应的引脚编号
uint8 addr; // 器件地址 七位地址模式
uint32 delay; // 模拟 IIC 软延时时长
}soft_iic_info_struct;
void soft_iic_write_8bit (soft_iic_info_struct *soft_iic_obj, const uint8 data);
void soft_iic_write_8bit_array (soft_iic_info_struct *soft_iic_obj, const uint8 *data, uint32 len);
void soft_iic_write_16bit (soft_iic_info_struct *soft_iic_obj, const uint16 data);
void soft_iic_write_16bit_array (soft_iic_info_struct *soft_iic_obj, const uint16 *data, uint32 len);
void soft_iic_write_8bit_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, const uint8 data);
void soft_iic_write_8bit_registers (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, const uint8 *data, uint32 len);
void soft_iic_write_16bit_register (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, const uint16 data);
void soft_iic_write_16bit_registers (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, const uint16 *data, uint32 len);
uint8 soft_iic_read_8bit (soft_iic_info_struct *soft_iic_obj);
void soft_iic_read_8bit_array (soft_iic_info_struct *soft_iic_obj, uint8 *data, uint32 len);
uint16 soft_iic_read_16bit (soft_iic_info_struct *soft_iic_obj);
void soft_iic_read_16bit_array (soft_iic_info_struct *soft_iic_obj, uint16 *data, uint32 len);
uint8 soft_iic_read_8bit_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name);
void soft_iic_read_8bit_registers (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, uint8 *data, uint32 len);
uint16 soft_iic_read_16bit_register (soft_iic_info_struct *soft_iic_obj, const uint16 register_name);
void soft_iic_read_16bit_registers (soft_iic_info_struct *soft_iic_obj, const uint16 register_name, uint16 *data, uint32 len);
void soft_iic_transfer_8bit_array (soft_iic_info_struct *soft_iic_obj, const uint8 *write_data, uint32 write_len, uint8 *read_data, uint32 read_len);
void soft_iic_transfer_16bit_array (soft_iic_info_struct *soft_iic_obj, const uint16 *write_data, uint32 write_len, uint16 *read_data, uint32 read_len);
void soft_iic_sccb_write_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name, uint8 data);
uint8 soft_iic_sccb_read_register (soft_iic_info_struct *soft_iic_obj, const uint8 register_name);
void soft_iic_init (soft_iic_info_struct *soft_iic_obj, uint8 addr, uint32 delay, gpio_pin_enum scl_pin, gpio_pin_enum sda_pin);
#endif

View File

@@ -0,0 +1,621 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_soft_spi
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_common_debug.h"
#include "zf_driver_soft_spi.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 延时
// 参数说明 void
// 返回参数 void
// 使用示例 soft_spi_delay(1);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
//static void soft_spi_delay (uint32 delay)
//{
// volatile uint32 count = delay;
// while(count --);
//}
#define soft_spi_delay(x) for(uint32 i = x; i--;)
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 8bit 数据读写
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 数据
// 返回参数 uint8 读取的数据
// 使用示例 soft_spi_8bit_data_handler(soft_spi_obj, 1);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static uint8 soft_spi_8bit_data_handler (soft_spi_info_struct *soft_spi_obj, const uint8 data)
{
uint8 temp = 0;
uint8 write_data = data;
uint8 read_data = 0;
if(soft_spi_obj->config.use_cs)
{
gpio_low(soft_spi_obj->cs_pin);
}
if(0 == soft_spi_obj->config.mode || 1 == soft_spi_obj->config.mode) // CPOL = 0 SCK 空闲低电平
{
gpio_low(soft_spi_obj->sck_pin);
}
else // CPOL = 1 SCK 空闲高电平
{
gpio_high(soft_spi_obj->sck_pin);
}
if(0 == soft_spi_obj->config.mode % 2) // CPHA = 0 第一个边沿采样
{
for(temp = 8; temp > 0; temp --)
{
if(0x80 & write_data)
{
gpio_high(soft_spi_obj->mosi_pin);
}
else
{
gpio_low(soft_spi_obj->mosi_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
write_data = write_data << 1;
read_data = read_data << 1;
if(soft_spi_obj->config.use_miso)
{
read_data |= gpio_get_level(soft_spi_obj->miso_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
}
}
else // CPHA = 1 第二个边沿采样
{
for(temp = 8; 0 < temp; temp --)
{
gpio_toggle_level(soft_spi_obj->sck_pin);
if(0x80 & write_data)
{
gpio_high(soft_spi_obj->mosi_pin);
}
else
{
gpio_low(soft_spi_obj->mosi_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
write_data = write_data << 1;
read_data = read_data << 1;
if(soft_spi_obj->config.use_miso)
{
read_data |= gpio_get_level(soft_spi_obj->miso_pin);
}
soft_spi_delay(soft_spi_obj->delay);
}
}
if(soft_spi_obj->config.use_cs)
{
gpio_high(soft_spi_obj->cs_pin);
}
return read_data;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 16bit 数据读写
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 数据
// 返回参数 uint16 读取的数据
// 使用示例 soft_spi_16bit_data_handler(soft_spi_obj, 1);
// 备注信息 内部调用
//-------------------------------------------------------------------------------------------------------------------
static uint16 soft_spi_16bit_data_handler (soft_spi_info_struct *soft_spi_obj, const uint16 data)
{
uint8 temp = 0;
uint16 write_data = data;
uint16 read_data = 0;
if(soft_spi_obj->config.use_cs)
{
gpio_low(soft_spi_obj->cs_pin);
}
if(0 == soft_spi_obj->config.mode || 1 == soft_spi_obj->config.mode) // CPOL = 0 SCK 空闲低电平
{
gpio_low(soft_spi_obj->sck_pin);
}
else // CPOL = 1 SCK 空闲高电平
{
gpio_high(soft_spi_obj->sck_pin);
}
if(0 == soft_spi_obj->config.mode % 2) // CPHA = 0 第一个边沿采样
{
for(temp = 16; 0 < temp; temp --)
{
if(0x8000 & write_data)
{
gpio_high(soft_spi_obj->mosi_pin);
}
else
{
gpio_low(soft_spi_obj->mosi_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
write_data = write_data << 1;
read_data = read_data << 1;
if(soft_spi_obj->config.use_miso)
{
read_data |= gpio_get_level(soft_spi_obj->miso_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
}
}
else // CPHA = 1 第二个边沿采样
{
for(temp = 16; 0 < temp; temp --)
{
gpio_toggle_level(soft_spi_obj->sck_pin);
if(write_data & 0x8000)
{
gpio_high(soft_spi_obj->mosi_pin);
}
else
{
gpio_low(soft_spi_obj->mosi_pin);
}
soft_spi_delay(soft_spi_obj->delay);
gpio_toggle_level(soft_spi_obj->sck_pin);
write_data = write_data << 1;
read_data = read_data << 1;
if(soft_spi_obj->config.use_miso)
{
read_data |= gpio_get_level(soft_spi_obj->miso_pin);
}
soft_spi_delay(soft_spi_obj->delay);
}
}
if(soft_spi_obj->config.use_cs)
{
gpio_high(soft_spi_obj->cs_pin);
}
return read_data;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口写 8bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 发送的数据
// 返回参数 void
// 使用示例 soft_spi_write_8bit(&soft_spi_obj, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_8bit (soft_spi_info_struct *soft_spi_obj, const uint8 data)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_8bit_data_handler(soft_spi_obj, data);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口写 8bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_write_8bit_array(&soft_spi_obj, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_8bit_array (soft_spi_info_struct *soft_spi_obj, const uint8 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
while(len --)
{
soft_spi_8bit_data_handler(soft_spi_obj, *data ++);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口写 16bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 发送的数据
// 返回参数 void
// 使用示例 soft_spi_write_16bit(&soft_spi_obj, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_16bit (soft_spi_info_struct *soft_spi_obj, uint16 data)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_16bit_data_handler(soft_spi_obj, data);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口写 16bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_write_16bit_array(&soft_spi_obj, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_16bit_array (soft_spi_info_struct *soft_spi_obj, const uint16 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
while(len --)
{
soft_spi_16bit_data_handler(soft_spi_obj, *data ++);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口向传感器的寄存器写 8bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 data 发送的数据
// 返回参数 void
// 使用示例 soft_spi_write_8bit_register(&soft_spi_obj, 1, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_8bit_register (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, const uint8 data)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_8bit_data_handler(soft_spi_obj, register_name);
soft_spi_8bit_data_handler(soft_spi_obj, data);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口向传感器的寄存器写 8bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_write_8bit_registers(&soft_spi_obj, 1, buf, 16);
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_8bit_registers (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, const uint8 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
soft_spi_8bit_data_handler(soft_spi_obj, register_name);
while(len --)
{
soft_spi_8bit_data_handler(soft_spi_obj, *data ++);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口向传感器的寄存器写 16bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 data 发送的数据
// 返回参数 void
// 使用示例 soft_spi_write_16bit_register(&soft_spi_obj, 1, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_16bit_register (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, uint16 data)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_16bit_data_handler(soft_spi_obj, register_name);
soft_spi_16bit_data_handler(soft_spi_obj, data);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口向传感器的寄存器写 16bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_write_16bit_registers(&soft_spi_obj, 1, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_write_16bit_registers (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, const uint16 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
soft_spi_16bit_data_handler(soft_spi_obj, register_name);
while(len --)
{
soft_spi_16bit_data_handler(soft_spi_obj, *data ++);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口读 8bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 发送的数据
// 返回参数 uint8 返回读取的 8bit 数据
// 使用示例 soft_spi_read_8bit(&soft_spi_obj);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 soft_spi_read_8bit (soft_spi_info_struct *soft_spi_obj)
{
zf_assert(soft_spi_obj != NULL);
return soft_spi_8bit_data_handler(soft_spi_obj, 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口读 8bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_read_8bit_array(&soft_spi_obj, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_read_8bit_array (soft_spi_info_struct *soft_spi_obj, uint8 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
while(len --)
{
*data ++ = soft_spi_8bit_data_handler(soft_spi_obj, 0);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口读 16bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 data 发送的数据
// 返回参数 uint16 返回读取的 16bit 数据
// 使用示例 soft_spi_read_16bit(&soft_spi_obj);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint16 soft_spi_read_16bit (soft_spi_info_struct *soft_spi_obj)
{
zf_assert(soft_spi_obj != NULL);
return soft_spi_16bit_data_handler(soft_spi_obj, 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口读 16bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_read_16bit_array(&soft_spi_obj, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_read_16bit_array (soft_spi_info_struct *soft_spi_obj, uint16 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
while(len --)
{
*data ++ = soft_spi_16bit_data_handler(soft_spi_obj, 0);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口从传感器的寄存器读 8bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 data 发送的数据
// 返回参数 uint8 返回读取的 8bit 数据
// 使用示例 soft_spi_read_8bit_register(&soft_spi_obj, 0x01, 0x01);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint8 soft_spi_read_8bit_register (soft_spi_info_struct *soft_spi_obj, const uint8 register_name)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_8bit_data_handler(soft_spi_obj, register_name);
return soft_spi_8bit_data_handler(soft_spi_obj, 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口从传感器的寄存器读 8bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_read_8bit_registers(&soft_spi_obj, 0x01, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_read_8bit_registers (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, uint8 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
soft_spi_8bit_data_handler(soft_spi_obj, register_name);
while(len --)
{
*data ++ = soft_spi_8bit_data_handler(soft_spi_obj, 0);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口从传感器的寄存器读 16bit 数据
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 data 发送的数据
// 返回参数 uint16 返回读取的 16bit 数据
// 使用示例 soft_spi_read_16bit_register(&soft_spi_obj, 0x0101);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint16 soft_spi_read_16bit_register (soft_spi_info_struct *soft_spi_obj, const uint16 register_name)
{
zf_assert(soft_spi_obj != NULL);
soft_spi_16bit_data_handler(soft_spi_obj, register_name);
return soft_spi_16bit_data_handler(soft_spi_obj, 0);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口从传感器的寄存器读 16bit 数组
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 soft_spi_read_16bit_registers(&soft_spi_obj, 0x0101, buf, 16);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_read_16bit_registers (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, uint16 *data, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(data != NULL);
soft_spi_16bit_data_handler(soft_spi_obj, register_name);
while(len --)
{
*data ++ = soft_spi_16bit_data_handler(soft_spi_obj, 0);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 8bit 数据传输 发送与接收数据是同时进行的
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 write_buffer 发送的数据缓冲区地址
// 参数说明 read_buffer 发送数据时接收到的数据的存储地址(不需要接收则传 NULL)
// 参数说明 len 发送的字节数
// 返回参数 void
// 使用示例 soft_spi_transfer_8bit(&soft_spi_obj, buf, buf, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_transfer_8bit (soft_spi_info_struct *soft_spi_obj, const uint8 *write_buffer, uint8 *read_buffer, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(write_buffer != NULL);
while(len --)
{
if(read_buffer != NULL)
{
*read_buffer = soft_spi_8bit_data_handler(soft_spi_obj, *write_buffer);
write_buffer ++;
read_buffer ++;
}
else
{
soft_spi_8bit_data_handler(soft_spi_obj, *write_buffer);
write_buffer ++;
}
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 16bit 数据传输 发送与接收数据是同时进行的
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 write_buffer 发送的数据缓冲区地址
// 参数说明 read_buffer 发送数据时接收到的数据的存储地址(不需要接收则传 NULL)
// 参数说明 len 发送的字节数
// 返回参数 void
// 使用示例 soft_spi_transfer_16bit(&soft_spi_obj, buf, buf, 1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_transfer_16bit (soft_spi_info_struct *soft_spi_obj, const uint16 *write_buffer, uint16 *read_buffer, uint32 len)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(write_buffer != NULL);
while(len --)
{
if(read_buffer != NULL)
{
*read_buffer = soft_spi_16bit_data_handler(soft_spi_obj, *write_buffer);
write_buffer ++;
read_buffer ++;
}
else
{
soft_spi_16bit_data_handler(soft_spi_obj, *write_buffer);
write_buffer ++;
}
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 软件 SPI 接口初始化
// 参数说明 *soft_spi_obj 软件 SPI 指定信息存放结构体的指针
// 参数说明 mode SPI 模式 参照 zf_driver_spi.h 内 spi_mode_enum 枚举体定义
// 参数说明 delay 软件 SPI 延时 就是时钟高电平时间 越短 SPI 速率越高
// 参数说明 sck_pin 选择 SCK 引脚 参照 zf_driver_gpio.h 内 gpio_pin_enum 枚举体定义
// 参数说明 mosi_pin 选择 MOSI 引脚 参照 zf_driver_gpio.h 内 gpio_pin_enum 枚举体定义
// 参数说明 miso_pin 选择 MISO 引脚 如果不需要这个引脚 就填 SOFT_SPI_PIN_NULL
// 参数说明 cs_pin 选择 CS 引脚 如果不需要这个引脚 就填 SOFT_SPI_PIN_NULL
// 返回参数 void
// 使用示例 spi_init(SPI_1, 0, 1*1000*1000, A5, A7, A6, A4);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void soft_spi_init (soft_spi_info_struct *soft_spi_obj, uint8 mode, uint32 delay, gpio_pin_enum sck_pin, gpio_pin_enum mosi_pin, uint32 miso_pin, uint32 cs_pin)
{
zf_assert(soft_spi_obj != NULL);
zf_assert(sck_pin != mosi_pin); // sck_pin 与 mosi_pin 怎么能填同一个引脚?
zf_assert(sck_pin != miso_pin); // sck_pin 与 miso_pin 怎么能填同一个引脚?
zf_assert(sck_pin != cs_pin); // sck_pin 与 cs_pin 怎么能填同一个引脚?
zf_assert(mosi_pin != miso_pin); // mosi_pin 与 miso_pin 怎么能填同一个引脚?
zf_assert(mosi_pin != cs_pin); // mosi_pin 与 cs_pin 怎么能填同一个引脚?
zf_assert((miso_pin != cs_pin) || (cs_pin == SOFT_SPI_PIN_NULL)); // miso_pin 与 cs_pin 怎么能填同一个引脚?
zf_assert(4 > mode); // 参照 zf_driver_spi.h 内 spi_mode_enum 枚举体定义
soft_spi_obj->config.mode = mode;
soft_spi_obj->delay = delay;
soft_spi_obj->sck_pin = sck_pin;
soft_spi_obj->mosi_pin = mosi_pin;
if(0 == mode || 1 == mode)
{
gpio_init(sck_pin, GPO, GPIO_LOW, GPO_PUSH_PULL); // IO 初始化
}
else
{
gpio_init(sck_pin, GPO, GPIO_HIGH, GPO_PUSH_PULL); // IO 初始化
}
gpio_init(mosi_pin, GPO, GPIO_HIGH, GPO_PUSH_PULL); // IO 初始化
if(SOFT_SPI_PIN_NULL == miso_pin)
{
soft_spi_obj->config.use_miso = 0;
}
else
{
soft_spi_obj->config.use_miso = 1;
soft_spi_obj->miso_pin = (gpio_pin_enum)miso_pin;
gpio_init(soft_spi_obj->miso_pin, GPI, GPIO_HIGH, GPI_FLOATING_IN); // IO 初始化
}
if(SOFT_SPI_PIN_NULL == cs_pin)
{
soft_spi_obj->config.use_cs = 0;
}
else
{
soft_spi_obj->config.use_cs = 1;
soft_spi_obj->cs_pin = (gpio_pin_enum)cs_pin;
gpio_init(soft_spi_obj->cs_pin, GPO, GPIO_HIGH, GPO_PUSH_PULL); // IO 初始化
}
}

View File

@@ -0,0 +1,91 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_soft_spi
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_soft_spi_h_
#define _zf_driver_soft_spi_h_
#include "zf_driver_gpio.h"
#define SOFT_SPI_PIN_NULL (0xFFFF) // 用于区分是否分配引脚
typedef struct
{
union
{
uint8 config_info; // 配置整体数据
struct
{
uint8 mode :6; // SPI 模式
uint8 use_miso :1; // 是否使用 MISO 引脚
uint8 use_cs :1; // 是否使用 CS 引脚
};
}config;
gpio_pin_enum sck_pin; // 用于记录对应的引脚编号
gpio_pin_enum mosi_pin; // 用于记录对应的引脚编号
gpio_pin_enum miso_pin; // 用于记录对应的引脚编号
gpio_pin_enum cs_pin; // 用于记录对应的引脚编号
uint32 delay; // 模拟 SPI 软延时时长
}soft_spi_info_struct;
void soft_spi_write_8bit (soft_spi_info_struct *soft_spi_obj, const uint8 data);
void soft_spi_write_8bit_array (soft_spi_info_struct *soft_spi_obj, const uint8 *data, uint32 len);
void soft_spi_write_16bit (soft_spi_info_struct *soft_spi_obj, const uint16 data);
void soft_spi_write_16bit_array (soft_spi_info_struct *soft_spi_obj, const uint16 *data, uint32 len);
void soft_spi_write_8bit_register (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, const uint8 data);
void soft_spi_write_8bit_registers (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, const uint8 *data, uint32 len);
void soft_spi_write_16bit_register (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, const uint16 data);
void soft_spi_write_16bit_registers (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, const uint16 *data, uint32 len);
uint8 soft_spi_read_8bit (soft_spi_info_struct *soft_spi_obj);
void soft_spi_read_8bit_array (soft_spi_info_struct *soft_spi_obj, uint8 *data, uint32 len);
uint16 soft_spi_read_16bit (soft_spi_info_struct *soft_spi_obj);
void soft_spi_read_16bit_array (soft_spi_info_struct *soft_spi_obj, uint16 *data, uint32 len);
uint8 soft_spi_read_8bit_register (soft_spi_info_struct *soft_spi_obj, const uint8 register_name);
void soft_spi_read_8bit_registers (soft_spi_info_struct *soft_spi_obj, const uint8 register_name, uint8 *data, uint32 len);
uint16 soft_spi_read_16bit_register (soft_spi_info_struct *soft_spi_obj, const uint16 register_name);
void soft_spi_read_16bit_registers (soft_spi_info_struct *soft_spi_obj, const uint16 register_name, uint16 *data, uint32 len);
void soft_spi_transfer_8bit (soft_spi_info_struct *soft_spi_obj, const uint8 *write_buffer, uint8 *read_buffer, uint32 len);
void soft_spi_transfer_16bit (soft_spi_info_struct *soft_spi_obj, const uint16 *write_buffer, uint16 *read_buffer, uint32 len);
void soft_spi_init (soft_spi_info_struct *soft_spi_obj, uint8 mode, uint32 delay, gpio_pin_enum sck_pin, gpio_pin_enum mosi_pin, uint32 miso_pin, uint32 cs_pin);
#endif

View File

@@ -0,0 +1,544 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_spi
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
#include "zf_driver_spi.h"
const uint32 spi_index[3] = {SPI1_BASE, SPI2_BASE, SPI3_BASE};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口写 8bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 data 数据
// 返回参数 void
// 使用示例 spi_write_8bit(SPI_1,0x11);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_8bit (spi_index_enum spi_n, const uint8 dat)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = dat; // 发送数据
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET); // 发送为空
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口写 8bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_write_8bit_array(SPI_1,data,64);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_8bit_array (spi_index_enum spi_n, const uint8 *dat, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = *(dat++);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口写 16bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 data 数据
// 返回参数 void
// 使用示例 spi_write_16bit(SPI_1,0x1101);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_16bit (spi_index_enum spi_n, const uint16 dat)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((dat & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(dat & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口写 16bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_write_16bit_array(SPI_1,data,64);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_16bit_array (spi_index_enum spi_n, const uint16 *dat, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((*dat & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(*dat++ & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口向传感器的寄存器写 8bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 data 数据
// 返回参数 void
// 使用示例 spi_write_8bit_register(SPI_1,0x11,0x01);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_8bit_register (spi_index_enum spi_n, const uint8 register_name, const uint8 dat)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = register_name;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = dat;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口向传感器的寄存器写 8bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_write_8bit_registers(SPI_1,0x11,data,32);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_8bit_registers (spi_index_enum spi_n, const uint8 register_name, const uint8 *dat, uint32 len)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = register_name;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = *dat++;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口向传感器的寄存器写 16bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 data 数据
// 返回参数 void
// 使用示例 spi_write_16bit_register(SPI_1,0x1011,0x0101);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_16bit_register (spi_index_enum spi_n, const uint16 register_name, const uint16 dat)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((register_name & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(register_name & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((dat & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(dat & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口向传感器的寄存器写 16bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_write_16bit_registers(SPI_1,0x1011,data,32);
//-------------------------------------------------------------------------------------------------------------------
void spi_write_16bit_registers (spi_index_enum spi_n, const uint16 register_name, const uint16 *dat, uint32 len)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((register_name & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(register_name & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((*dat & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(*dat++ & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口读 8bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 返回参数 uint8 数据
// 使用示例 spi_read_8bit(SPI_1);
//-------------------------------------------------------------------------------------------------------------------
uint8 spi_read_8bit (spi_index_enum spi_n)
{
uint8 dat = 0;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
return dat;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口读 8bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 发送缓冲区长度
// 返回参数 void
// 使用示例 spi_read_8bit_array(SPI_1,data,64);
//-------------------------------------------------------------------------------------------------------------------
void spi_read_8bit_array (spi_index_enum spi_n, uint8 *dat, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*dat++ = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口读 16bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 返回参数 uint16 数据
// 使用示例 spi_read_16bit(SPI_1);
//-------------------------------------------------------------------------------------------------------------------
uint16 spi_read_16bit (spi_index_enum spi_n)
{
uint16 dat = 0;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
dat = ((dat << 8)| ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR);
return dat;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口读 16bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 发送缓冲区长度
// 返回参数 void
// 使用示例 spi_read_16bit_array(SPI_1,data,64);
//-------------------------------------------------------------------------------------------------------------------
void spi_read_16bit_array (spi_index_enum spi_n, uint16 *dat, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*dat = ((*dat << 8)| ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR);
dat++;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口从传感器的寄存器读 8bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 返回参数 uint8 数据
// 使用示例 spi_read_8bit_register(SPI_1,0x11);
//-------------------------------------------------------------------------------------------------------------------
uint8 spi_read_8bit_register (spi_index_enum spi_n, const uint8 register_name)
{
uint8 dat;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = register_name;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 2;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
return dat;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口从传感器的寄存器读 8bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 发送缓冲区长度
// 返回参数 void
// 使用示例 spi_read_8bit_registers(SPI_1,0x11,data,32);
//-------------------------------------------------------------------------------------------------------------------
void spi_read_8bit_registers (spi_index_enum spi_n, const uint8 register_name, uint8 *dat, uint32 len)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = register_name;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY));
*dat++ = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口从传感器的寄存器读 16bit 数据
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 返回参数 uint16 数据
// 使用示例 spi_read_16bit_register(SPI_1,0x1011);
//-------------------------------------------------------------------------------------------------------------------
uint16 spi_read_16bit_register (spi_index_enum spi_n, const uint16 register_name)
{
uint16 dat = 0;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((register_name & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(register_name & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
dat = ((dat << 8)| ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR);
return dat;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口从传感器的寄存器读 16bit 数组
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 register_name 寄存器地址
// 参数说明 *data 数据存放缓冲区
// 参数说明 len 发送缓冲区长度
// 返回参数 void
// 使用示例 spi_read_16bit_registers(SPI_1,0x1101,data,32);
//-------------------------------------------------------------------------------------------------------------------
void spi_read_16bit_registers (spi_index_enum spi_n, const uint16 register_name, uint16 *dat, uint32 len)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)((register_name & 0xFF00)>>8);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (uint8)(register_name & 0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*dat = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = 0;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*dat = ((*dat << 8)| ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR);
dat++;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 8bit 数据传输 发送与接收数据是同时进行的
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 write_buffer 发送的数据缓冲区地址
// 参数说明 read_buffer 发送数据时接收到的数据的存储地址(不需要接收则传 NULL)
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_transfer_8bit(SPI_1,buf,buf,1);
//-------------------------------------------------------------------------------------------------------------------
void spi_transfer_8bit (spi_index_enum spi_n,const uint8 *write_buffer, uint8 *read_buffer, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = *(write_buffer++);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
if(read_buffer != NULL)
{
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*read_buffer++ = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 16bit 数据传输 发送与接收数据是同时进行的
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 write_buffer 发送的数据缓冲区地址
// 参数说明 read_buffer 发送数据时接收到的数据的存储地址(不需要接收则传 NULL)
// 参数说明 len 缓冲区长度
// 返回参数 void
// 使用示例 spi_transfer_16bit(SPI_1,buf,buf,1);
//-------------------------------------------------------------------------------------------------------------------
void spi_transfer_16bit (spi_index_enum spi_n, const uint16 *write_buffer, uint16 *read_buffer, uint32 len)
{
while(len--)
{
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (*write_buffer&0xFF00)>>8;
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
if(read_buffer != NULL)
{
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*read_buffer++ = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
((SPI_TypeDef *)(spi_index[spi_n]))->DATAR = (*write_buffer&0x00FF);
while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_BSY) != RESET);
if(read_buffer != NULL)
{
//while((((SPI_TypeDef *)(spi_index[spi_n]))->STATR & SPI_I2S_FLAG_RXNE) == RESET);
*read_buffer = ((SPI_TypeDef *)(spi_index[spi_n]))->DATAR;
}
write_buffer++;
read_buffer++;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 SPI 接口初始化
// 参数说明 spi_n SPI 模块号 参照 zf_driver_spi.h 内 spi_index_enum 枚举体定义
// 参数说明 mode SPI 模式 参照 zf_driver_spi.h 内 spi_mode_enum 枚举体定义
// 参数说明 baud 设置 SPI 的波特率 不超过系统时钟的一半 部分速率会被适配成相近的速率
// 参数说明 sck_pin 选择 SCK 引脚 参照 zf_driver_spi.h 内 spi_pin_enum 枚举体定义
// 参数说明 mosi_pin 选择 MOSI 引脚 参照 zf_driver_spi.h 内 spi_pin_enum 枚举体定义
// 参数说明 miso_pin 选择 MISO 引脚 参照 zf_driver_spi.h 内 spi_pin_enum 枚举体定义
// 参数说明 cs_pin 选择 CS 引脚 参照 zf_driver_gpio.h 内 gpio_pin_enum 枚举体定义
// 返回参数 void
// 使用示例 spi_init(SPI_1, 0, 1*1000*1000, SPI1_SCK_A5, SPI1_MOSI_A7, SPI1_MISO_A6, A4); //硬件SPI初始化 模式0 波特率为1Mhz
//-------------------------------------------------------------------------------------------------------------------
void spi_init(spi_index_enum spi_n, spi_mode_enum mode, uint32 baud, spi_pin_enum sck_pin, spi_pin_enum mosi_pin, spi_pin_enum miso_pin, gpio_pin_enum cs_pin)
{
SPI_I2S_DeInit((SPI_TypeDef *)(spi_index[spi_n]));
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 复用总线使能
if(sck_pin == SPI1_MAP1_SCK_B3 && mosi_pin == SPI1_MAP1_MOSI_B5)
{
GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
}
else if(sck_pin == SPI3_MAP1_SCK_C10 && mosi_pin == SPI3_MAP1_MOSI_C12)
{
GPIO_PinRemapConfig(GPIO_Remap_SPI3, ENABLE);
}
if(SPI_1 == spi_n) RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1时钟使能
else if(SPI_2 == spi_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // SPI2时钟使能
else if(SPI_3 == spi_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); // SPI3时钟使能
gpio_init(sck_pin & 0xFF, GPO, 1, SPEED_50MHZ|GPO_AF_PUSH_PULL);
gpio_init(mosi_pin & 0xFF, GPO, 1, SPEED_50MHZ|GPO_AF_PUSH_PULL);
if(miso_pin != SPI_MISO_NULL)
{
gpio_init(miso_pin & 0xFF, GPI, 1, SPEED_50MHZ|GPI_PULL_UP);
}
if(cs_pin != PIN_NULL)
{
gpio_init(cs_pin & 0xFF, GPO, 0, SPEED_50MHZ|GPO_PUSH_PULL);
}
SPI_InitTypeDef SPI_InitStructure = {0};
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 设置SPI的数据大小:SPI发送接收8位帧结构
switch(mode)
{
case SPI_MODE0:
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 串行同步时钟的空闲状态为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 串行同步时钟的第一个跳变沿(上升或下降)数据被采样
}break;
case SPI_MODE1:
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 串行同步时钟的空闲状态为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 串行同步时钟的第二个跳变沿(上升或下降)数据被采样
}break;
case SPI_MODE2:
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 串行同步时钟的第一个跳变沿(上升或下降)数据被采样
}break;
case SPI_MODE3:
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 串行同步时钟的第二个跳变沿(上升或下降)数据被采样
}break;
}
uint16 psc = 0;
psc = system_clock / baud; // 计算分频值
if((system_clock % baud)== 0)
{
psc = psc - 1;
}
if(psc >= 128) psc = SPI_BaudRatePrescaler_256; // CLK_0.5625M
else if(psc >= 64) psc = SPI_BaudRatePrescaler_128; // CLK_1.125M
else if(psc >= 32) psc = SPI_BaudRatePrescaler_64; // CLK_2.25M
else if(psc >= 16) psc = SPI_BaudRatePrescaler_32; // CLK_4.5M
else if(psc >= 8) psc = SPI_BaudRatePrescaler_16; // CLK_9M
else if(psc >= 4) psc = SPI_BaudRatePrescaler_8; // CLK_18M
else if(psc >= 2) psc = SPI_BaudRatePrescaler_4; // CLK_36M
else if(psc >= 1) psc = SPI_BaudRatePrescaler_2; // CLK_72M
else zf_assert(0);
SPI_InitStructure.SPI_BaudRatePrescaler = psc; // 定义波特率预分频的值
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 主机模式使用软件控制NSS引脚
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init((SPI_TypeDef *)(spi_index[spi_n]), &SPI_InitStructure); // 根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(((SPI_TypeDef *)(spi_index[spi_n])), ENABLE); // 使能SPI外设
}

View File

@@ -0,0 +1,145 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_spi
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_spi_h
#define _zf_driver_spi_h
#include "ch32v30x_spi.h"
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "zf_common_debug.h"
#include "zf_common_clock.h"
#include "zf_driver_gpio.h"
#define SPI_SPEED_PRIORITY // SPI 通信速度优先
// 此枚举定义不允许用户修改
typedef enum // 枚举串口号
{
SPI_1 = 0x00,
SPI_2 = 0x01,
SPI_3 = 0x02
}spi_index_enum;
// 此枚举定义不允许用户修改
typedef enum // 枚举串口号
{
//----------SPI1----------
// 以下为SPI1的一组映射引脚不允许映射引脚混用。
// 例如SPI1_MAP0_MAP_SCK_A5与SPI1_MAP1_MAP_MISO_B4不能一起使用。
// 只允许SPI1_MAP0_MAP_SCK_A5 和 SPI1_MAP0_MAP_MISO_A6和 SPI1_MAP0_MAP_MOSI_A7 同组映射引脚一起使用
// 默认映射
SPI1_MAP0_SCK_A5 = 0x0000 | A5,
SPI1_MAP0_MISO_A6 = 0x0000 | A6,
SPI1_MAP0_MOSI_A7 = 0x0000 | A7,
// 以下为SPI1的一组映射引脚不允许映射引脚混用。
// 重映射
SPI1_MAP1_SCK_B3 = 0x0100 | B3,
SPI1_MAP1_MISO_B4 = 0x0100 | B4,
SPI1_MAP1_MOSI_B5 = 0x0100 | B5,
//----------SPI2-- --------
// 以下为SPI2的一组映射引脚不允许映射引脚混用。
// 默认映射
SPI2_MAP0_SCK_B13 = 0x1000 | B13,
SPI2_MAP0_MISO_B14 = 0x1000 | B14,
SPI2_MAP0_MOSI_B15 = 0x1000 | B15,
//----------SPI3-- --------
// 以下为SPI3的一组映射引脚不允许映射引脚混用。
// 默认映射
SPI3_MAP0_SCK_B3 = 0x2000 | B3,
SPI3_MAP0_MISO_B4 = 0x2000 | B4,
SPI3_MAP0_MOSI_B5 = 0x2000 | B5,
// 以下为SPI3的一组映射引脚不允许映射引脚混用。
// 重映射
SPI3_MAP1_SCK_C10 = 0x2100 | C10,
SPI3_MAP1_MISO_C11 = 0x2100 | C11,
SPI3_MAP1_MOSI_C12 = 0x2100 | C12,
// 不需要MISO引脚就用此定义
SPI_MISO_NULL = 0xFFFE,
// 不需要CS引脚就用此定义
SPI_CS_NULL = 0xFF,
}spi_pin_enum;
typedef enum // 枚举 SPI 模式 此枚举定义不允许用户修改
{
SPI_MODE0,
SPI_MODE1,
SPI_MODE2,
SPI_MODE3,
}spi_mode_enum;
void spi_write_8bit (spi_index_enum spi_n, const uint8 data);
void spi_write_8bit_array (spi_index_enum spi_n, const uint8 *data, uint32 len);
void spi_write_16bit (spi_index_enum spi_n, const uint16 data);
void spi_write_16bit_array (spi_index_enum spi_n, const uint16 *data, uint32 len);
void spi_write_8bit_register (spi_index_enum spi_n, const uint8 register_name, const uint8 data);
void spi_write_8bit_registers (spi_index_enum spi_n, const uint8 register_name, const uint8 *data, uint32 len);
void spi_write_16bit_register (spi_index_enum spi_n, const uint16 register_name, const uint16 data);
void spi_write_16bit_registers (spi_index_enum spi_n, const uint16 register_name, const uint16 *data, uint32 len);
uint8 spi_read_8bit (spi_index_enum spi_n);
void spi_read_8bit_array (spi_index_enum spi_n, uint8 *data, uint32 len);
uint16 spi_read_16bit (spi_index_enum spi_n);
void spi_read_16bit_array (spi_index_enum spi_n, uint16 *data, uint32 len);
uint8 spi_read_8bit_register (spi_index_enum spi_n, const uint8 register_name);
void spi_read_8bit_registers (spi_index_enum spi_n, const uint8 register_name, uint8 *data, uint32 len);
uint16 spi_read_16bit_register (spi_index_enum spi_n, const uint16 register_name);
void spi_read_16bit_registers (spi_index_enum spi_n, const uint16 register_name, uint16 *data, uint32 len);
void spi_transfer_8bit (spi_index_enum spi_n, const uint8 *write_buffer, uint8 *read_buffer, uint32 len);
void spi_transfer_16bit (spi_index_enum spi_n, const uint16 *write_buffer, uint16 *read_buffer, uint32 len);
void spi_init (spi_index_enum spi_n, spi_mode_enum mode, uint32 baud, spi_pin_enum sck_pin, spi_pin_enum mosi_pin, spi_pin_enum miso_pin, gpio_pin_enum cs_pin);
#endif

View File

@@ -0,0 +1,289 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_timer
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
#include "zf_driver_timer.h"
// 该数组禁止修改,内部使用,用户无需关心
static timer_function_enum timer_function_state[10] =
{
TIMER_FUNCTION_INIT, TIMER_FUNCTION_INIT,
TIMER_FUNCTION_INIT, TIMER_FUNCTION_INIT,
TIMER_FUNCTION_INIT, TIMER_FUNCTION_INIT,
TIMER_FUNCTION_INIT, TIMER_FUNCTION_INIT,
TIMER_FUNCTION_INIT, TIMER_FUNCTION_INIT
};
// 该数组禁止修改,内部使用,用户无需关心
static timer_mode_enum timer_mode_state[10] =
{
TIMER_SYSTEM_CLOCK, TIMER_SYSTEM_CLOCK,
TIMER_SYSTEM_CLOCK, TIMER_SYSTEM_CLOCK,
TIMER_SYSTEM_CLOCK, TIMER_SYSTEM_CLOCK,
TIMER_SYSTEM_CLOCK, TIMER_SYSTEM_CLOCK,
TIMER_SYSTEM_CLOCK, TIMER_SYSTEM_CLOCK
};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 TIMER 外设确认功能状态 库内部调用
// 参数说明 index TIMER 外设模块号
// 参数说明 mode 需要确的功能模块
// 返回参数 uint8 1-可以使用 0-不可以使用
// 使用示例 zf_assert(timer_funciton_check(TIM_1, TIMER_FUNCTION_PWM);
//-------------------------------------------------------------------------------------------------------------------
uint8 timer_funciton_check (timer_index_enum index, timer_function_enum mode)
{
uint8 return_state = 1;
if(TIMER_FUNCTION_INIT == timer_function_state[index])
{
timer_function_state[index] = mode;
}
else if(timer_function_state[index] == mode)
{
return_state = 1;
}
else
{
return_state = 0;
}
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 定时器时钟总线初始化
// 参数说明 timer_ch 定时器通道
// 返回参数 void
// 备注信息 内部使用,用户无需关心
//-------------------------------------------------------------------------------------------------------------------
void timer_clock_enable(timer_index_enum index)
{
if(TIM_1 == index) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能定时器1的时钟
else if(TIM_2 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟
else if(TIM_3 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3的时钟
else if(TIM_4 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟
else if(TIM_5 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);//使能定时器5的时钟
else if(TIM_6 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);//使能定时器6的时钟
else if(TIM_7 == index) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//使能定时器7的时钟
else if(TIM_8 == index) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);//使能定时器8的时钟
else if(TIM_9 == index) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);//使能定时器9的时钟
else if(TIM_10== index) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,ENABLE);//使能定时器10的时钟
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 计时器开始
// 参数说明 timer_ch 选择模块的通道 (选择范围 由TIMERN_enum枚举值的内容确定)
// 返回参数 void
// 使用示例 timer_start(TIM_1, TIMER_US); //定时器1 开始计数每一us计数一次
//-------------------------------------------------------------------------------------------------------------------
void timer_start(timer_index_enum index)
{
TIM_TypeDef *tim_index = TIM1;
switch(index)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
TIM_Cmd(tim_index, ENABLE); // 使能TIMx
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 关闭计时器
// 参数说明 timer_ch 选择模块的通道 (选择范围 由TIMERN_enum枚举值的内容确定)
// 返回参数 void
// 备注信息 关闭定时器并清除标志位
//-------------------------------------------------------------------------------------------------------------------
void timer_stop(timer_index_enum index)
{
TIM_TypeDef *tim_index = TIM1;
switch(index)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
TIM_Cmd(tim_index, DISABLE); //失能TIM
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 获取计时器值
// 参数说明 timer_ch 选择模块的通道 (选择范围 由TIMERN_enum枚举值的内容确定)
// 返回参数 uint32 计数值
// 使用示例 timer_get(TIM_1) //获取定时器1的计时时间
//-------------------------------------------------------------------------------------------------------------------
uint16 timer_get(timer_index_enum index)
{
TIM_TypeDef *tim_index = TIM1;
uint16 return_value = 0;
switch(index)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
if(timer_mode_state[index] == TIMER_MS)
{
return_value = tim_index->CNT/3;
}
else
{
return_value = tim_index->CNT;
}
return return_value;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 TIMER 清除计时器计数
// 参数说明 index TIMER 外设模块号
// 返回参数 void
// 使用示例 timer_clear(TIM_1);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void timer_clear (timer_index_enum index)
{
TIM_TypeDef *tim_index = TIM1;
switch(index)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
tim_index->CNT = 0;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 TIMER 计时器初始化
// 参数说明 index TIMER 外设模块号
// 参数说明 mode 计时方式
// 返回参数 void
// 使用示例 timer_init(TIM_1, TIMER_US);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void timer_init(timer_index_enum index, timer_mode_enum mode)
{
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// 这里是检查是否有重复使用定时器
// 比如初始化了 TIM1_PWM 然后又初始化成 TIM_1 这种用法是不允许的
zf_assert(timer_funciton_check(index, TIMER_FUNCTION_TIMER));
timer_function_state[index] = TIMER_FUNCTION_TIMER;
TIM_TypeDef *tim_index = TIM1;
switch(index)
{
case TIM_1: tim_index = ((TIM_TypeDef *)TIM1_BASE); break;
case TIM_2: tim_index = ((TIM_TypeDef *)TIM2_BASE); break;
case TIM_3: tim_index = ((TIM_TypeDef *)TIM3_BASE); break;
case TIM_4: tim_index = ((TIM_TypeDef *)TIM4_BASE); break;
case TIM_5: tim_index = ((TIM_TypeDef *)TIM5_BASE); break;
case TIM_6: tim_index = ((TIM_TypeDef *)TIM6_BASE); break;
case TIM_7: tim_index = ((TIM_TypeDef *)TIM7_BASE); break;
case TIM_8: tim_index = ((TIM_TypeDef *)TIM8_BASE); break;
case TIM_9: tim_index = ((TIM_TypeDef *)TIM9_BASE); break;
case TIM_10: tim_index = ((TIM_TypeDef *)TIM10_BASE); break;
}
timer_clock_enable(index); // 开启时钟总线
timer_mode_state[index] = mode;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
if(mode == TIMER_US)
{
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 装载自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = (system_clock/1000000)-1; // 装载预分频
}
else if(mode == TIMER_MS)
{
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 装载自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = (system_clock/1000)/3-1; // 装载预分频
}
else
{
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 装载自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 装载预分频
}
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器设置为0
TIM_TimeBaseInit(tim_index, &TIM_TimeBaseStructure); // 根据指定的参数初始化TIMx的时间基数单位
TIM_Cmd(tim_index, ENABLE); // 使能TIMx
}

View File

@@ -0,0 +1,93 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_timer
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_timer_h
#define _zf_driver_timer_h
#include "ch32v30x_rcc.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_tim.h"
#include "zf_common_debug.h"
#include "zf_common_clock.h"
//此枚举定义不允许用户修改
typedef enum
{
TIM_1,
TIM_2,
TIM_3,
TIM_4,
TIM_5,
TIM_6,
TIM_7,
TIM_8,
TIM_9,
TIM_10,
}timer_index_enum;
typedef enum
{
TIMER_SYSTEM_CLOCK, // 系统频率计时 最大 0xFFFF
TIMER_US, // 微秒计时 最大 0xFFFF
TIMER_MS, // 毫秒计时 最大 0xFFFF/2
}timer_mode_enum;
typedef enum
{
TIMER_FUNCTION_INIT = 0, // 功能未初始化
TIMER_FUNCTION_TIMER, // 用作 TIMER 计时
TIMER_FUNCTION_PIT, // 用作 PIT
TIMER_FUNCTION_PWM, // 用作 PWM
TIMER_FUNCTION_ENCODER, // 用作 ENCODER
TIMER_FUNCTION_CAMERA, // 用作 CAMERA
}timer_function_enum;
uint8 timer_funciton_check (timer_index_enum index, timer_function_enum mode);
void timer_clock_enable (timer_index_enum index);
void timer_start (timer_index_enum index);
void timer_stop (timer_index_enum index);
uint16 timer_get (timer_index_enum index);
void timer_clear (timer_index_enum index);
void timer_init (timer_index_enum index, timer_mode_enum mode);
#endif

View File

@@ -0,0 +1,292 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_uart
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_driver_gpio.h"
#include "zf_driver_uart.h"
// 该数组禁止修改,内部使用用户无需关心
const uint8 uart_irq[] = {USART1_IRQn, USART2_IRQn, USART3_IRQn, UART4_IRQn, UART5_IRQn, UART6_IRQn, UART7_IRQn, UART8_IRQn};
const uint32 uart_index[] = {USART1_BASE, USART2_BASE, USART3_BASE, UART4_BASE, UART5_BASE, UART6_BASE, UART7_BASE, UART8_BASE};
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 串口发送一个字节
// 参数说明 uartn 串口通道
// 参数说明 dat 串口数据
// 返回参数 void
// 使用示例 uart_write_byte(UART_1, 0x43); //串口1发送0x43。
//-------------------------------------------------------------------------------------------------------------------
void uart_write_byte(uart_index_enum uartn, const uint8 dat)
{
while((((USART_TypeDef*)uart_index[uartn])->STATR & USART_FLAG_TXE)==0);
((USART_TypeDef*)uart_index[uartn])->DATAR = dat;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 串口发送数组
// 参数说明 uartn 串口通道
// 参数说明 buff 要发送的数组地址
// 参数说明 len 数据长度
// 返回参数 void
// 使用示例 uart_write_buffer(UART_1, buff, 10); //串口1发送10个buff数组。
//-------------------------------------------------------------------------------------------------------------------
void uart_write_buffer(uart_index_enum uartn, const uint8 *buff, uint32 len)
{
zf_assert(buff != NULL);
while(len--)
uart_write_byte(uartn, *buff++);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 串口发送字符串
// 参数说明 uartn 串口通道
// 参数说明 str 字符串首地址
// 返回参数 void
// 使用示例 uart_putstr(UART_1, (uint8 *)"12345") //串口1发送12345这个字符串
//-------------------------------------------------------------------------------------------------------------------
void uart_write_string(uart_index_enum uartn, const char *str)
{
zf_assert(str != NULL);
while(*str) // 一直循环到结尾
{
uart_write_byte(uartn, *str++);
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 打开串口接收中断
// 参数说明 uartn 串口通道
// 参数说明 status 使能或者失能
// 返回参数 void
// 使用示例 uart_rx_irq(UART_1, ENABLE); //打开串口1接收中断
//-------------------------------------------------------------------------------------------------------------------
void uart_rx_interrupt(uart_index_enum uartn, uint8 status)
{
USART_ITConfig(((USART_TypeDef*)uart_index[uartn]), USART_IT_RXNE, status);
// 设置中断优先级
interrupt_set_priority((uint32)((IRQn_Type)uart_irq[uartn]), 0);
if(status) interrupt_enable((IRQn_Type)uart_irq[uartn]);
else interrupt_disable((IRQn_Type)uart_irq[uartn]);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 打开串口发送中断
// 参数说明 uartn 串口通道
// 参数说明 status 使能或者失能
// 返回参数 void
// 使用示例 uart_tx_irq(UART_1, DISABLE); //关闭串口1发送 中断
//-------------------------------------------------------------------------------------------------------------------
void uart_tx_interrupt(uart_index_enum uartn, uint8 status)
{
USART_ITConfig(((USART_TypeDef*)uart_index[uartn]), USART_IT_TXE, status);
// 设置中断优先级
interrupt_set_priority((uint32)((IRQn_Type)uart_irq[uartn]), 0);
if(status) interrupt_enable((IRQn_Type)uart_irq[uartn]);
else interrupt_disable((IRQn_Type)uart_irq[uartn]);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 读取串口接收的数据whlie等待
// 参数说明 uartn 串口模块号(UART_1 - UART_8)
// 参数说明 *dat 接收数据的地址
// 返回参数 void
// 使用示例 uint8 dat; uart_read_byte(USART_1,&dat); // 接收串口1数据 存在在dat变量里
//-------------------------------------------------------------------------------------------------------------------
uint8 uart_read_byte(uart_index_enum uartn)
{
while((((USART_TypeDef*)uart_index[uartn])->STATR & USART_FLAG_RXNE) == 0);
return (((USART_TypeDef*)uart_index[uartn])->DATAR & (uint16)0xFF);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 读取串口接收的数据(查询接收)
// 参数说明 uartn 串口模块号(UART_1 - UART_8)
// 参数说明 *dat 接收数据的地址
// 返回参数 uint8 1接收成功 0未接收到数据
// 使用示例 uint8 dat; uart_query_byte(USART_1,&dat); // 接收串口1数据 存在在dat变量里
//-------------------------------------------------------------------------------------------------------------------
uint8 uart_query_byte(uart_index_enum uartn, uint8 *dat)
{
if((((USART_TypeDef*)uart_index[uartn])->STATR & USART_FLAG_RXNE) != 0)
{
*dat = (((USART_TypeDef*)uart_index[uartn])->DATAR & 0xFF);
return 1;
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 串口初始化
// 参数说明 uartn 串口通道
// 参数说明 baud 波特率
// 参数说明 tx_pin 串口发送引脚号
// 参数说明 rx_pin 串口接收引脚号
// 返回参数 void
// 使用示例 uart_init(UART_1, 115200, UART1_TX_A9, UART1_RX_A10); //串口1初始化引脚号,TX为A9,RX为A10
//-------------------------------------------------------------------------------------------------------------------
void uart_init(uart_index_enum uart_n, uint32 baud, uart_pin_enum tx_pin, uart_pin_enum rx_pin)
{
// 如果程序在输出了断言信息 并且提示出错位置在这里
// 就去查看你在什么地方调用这个函数 检查你的传入参数
// RX和TX引脚需要传入同一组映射引脚如果不同就会进断言
zf_assert((tx_pin & (uart_n << 12)) == (rx_pin & (uart_n << 12))); // tx_pin 与 rx_pin 必须与 uart_n 匹配
zf_assert((tx_pin >> 8) == (rx_pin >> 8)); // tx_pin 与 rx_pin 必须成组传入
gpio_init(tx_pin & 0xFF, GPO, 0, GPO_AF_PUSH_PULL);
gpio_init(rx_pin & 0xFF, GPI, 0, GPI_PULL_UP);
// AFIO总线开启
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
switch(tx_pin & 0xFFFF)
{
case UART1_MAP1_TX_B6:
AFIO->PCFR2 &= ~(0x01<<26);
AFIO->PCFR1 &= ~(0x01<<2);
AFIO->PCFR1 |= (0x01<<2);
break;
case UART1_MAP2_TX_B15:
AFIO->PCFR2 &= ~(0x01<<26);
AFIO->PCFR2 |= (0x01<<26);
AFIO->PCFR1 &= ~(0x01<<2);
break;
case UART1_MAP3_TX_A6:
AFIO->PCFR2 &= ~(0x01<<26);
AFIO->PCFR2 |= (0x01<<26);
AFIO->PCFR1 &= ~(0x01<<2);
AFIO->PCFR1 |= (0x01<<2);
break;
case UART2_MAP1_TX_D5:
AFIO->PCFR1 &= ~(0x01<<3);
AFIO->PCFR1 |= (0x01<<3);
break;
case UART3_MAP1_TX_C10:
AFIO->PCFR1 &= ~(0x03<<4);
AFIO->PCFR1 |= (0x01<<4);
break;
case UART3_MAP2_TX_D8:
AFIO->PCFR1 &= ~(0x03<<4);
AFIO->PCFR1 |= (0x03<<4);
break;
case UART4_MAP1_TX_B0:
AFIO->PCFR2 &= ~(0x03<<16);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 16);
break;
case UART4_MAP3_TX_E0:
AFIO->PCFR2 &= ~(0x03<<16);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 16);
break;
case UART5_MAP1_TX_B4:
AFIO->PCFR2 &= ~(0x03<<18);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 18);
break;
case UART5_MAP3_TX_E8:
AFIO->PCFR2 &= ~(0x03<<18);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 18);
break;
case UART6_MAP1_TX_B8:
AFIO->PCFR2 &= ~(0x03<<20);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 20);
break;
case UART6_MAP3_TX_E10:
AFIO->PCFR2 &= ~(0x03<<20);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 20);
break;
case UART7_MAP1_TX_A6:
AFIO->PCFR2 &= ~(0x03<<22);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 22);
break;
case UART7_MAP3_TX_E12:
AFIO->PCFR2 &= ~(0x03<<22);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 22);
break;
case UART8_MAP1_TX_A14:
AFIO->PCFR2 &= ~(0x03<<24);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 24);
break;
case UART8_MAP3_TX_E14:
AFIO->PCFR2 &= ~(0x03<<24);
AFIO->PCFR2 |= (((tx_pin >> 8) & 0x03 ) << 24);
break;
}
// 串口总线使能
if(UART_1 == uart_n) RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
else if(UART_2 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
else if(UART_3 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
else if(UART_4 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
else if(UART_5 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
else if(UART_6 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART6, ENABLE);
else if(UART_7 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART7, ENABLE);
else if(UART_8 == uart_n) RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART8, ENABLE);
// 串口参数配置
USART_InitTypeDef USART_InitStructure = {0};
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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_Tx | USART_Mode_Rx;
// 使能串口
USART_Init((USART_TypeDef*)uart_index[uart_n], &USART_InitStructure);
USART_Cmd((USART_TypeDef*)uart_index[uart_n], ENABLE);
}

View File

@@ -0,0 +1,231 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_uart
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_uart_h
#define _zf_driver_uart_h
#include "ch32v30x.h"
#include "ch32v30x_gpio.h"
#include "ch32v30x_rcc.h"
#include "ch32v30x_usart.h"
#include "zf_common_interrupt.h"
#include "zf_common_debug.h"
#include "zf_driver_gpio.h"
// 此枚举定义不允许用户修改
// 初始化的时候必须使用同一组引脚例如UART1_MAP_TX_A9和UART1_MAP_RX_A10是一组引脚
//
typedef enum // 此枚举定义不允许用户修改
{
// MAP0 默认映射
// MAP1 重映射
// MAP2 部分映射
// MAP3 完全映射
//----------UART1-----------//
// 以下为串口1的一组映射引脚不允许映射引脚混用。
// 例如UART1_MAP0_TX_A9与UART1_MAP1_TX_B6不能一起使用。
// 默认映射
UART1_MAP0_TX_A9 = 0x0000 | A9 ,
UART1_MAP0_RX_A10 = 0x0000 | A10,
// 以下为串口1的一组映射引脚不允许映射引脚混用。
// 重映射
UART1_MAP1_TX_B6 = 0x0100 | B6 ,
UART1_MAP1_RX_B7 = 0x0100 | B7 ,
// 以下为串口1的一组映射引脚不允许映射引脚混用。
// 部分映射
UART1_MAP2_TX_B15 = 0x0200 | B15,
UART1_MAP2_RX_A8 = 0x0200 | A8 ,
// 以下为串口1的一组映射引脚不允许映射引脚混用。
// 完全映射
UART1_MAP3_TX_A6 = 0x0300 | A6 ,
UART1_MAP3_RX_A7 = 0x0300 | A7 ,
//----------UART2-----------//
// 以下为串口2的一组映射引脚不允许映射引脚混用。
// 默认映射
UART2_MAP0_TX_A2 = 0x1000 | A2 ,
UART2_MAP0_RX_A3 = 0x1000 | A3 ,
// 以下为串口2的一组映射引脚不允许映射引脚混用。
// 重映射
UART2_MAP1_TX_D5 = 0x1100 | D5 ,
UART2_MAP1_RX_D6 = 0x1100 | D6 ,
//----------UART3--------------//
// 以下为串口3的一组映射引脚不允许映射引脚混用。
// 默认映射
UART3_MAP0_TX_B10 = 0x2000 | B10, // 下载器串口默认引脚
UART3_MAP0_RX_B11 = 0x2000 | B11, // 下载器串口默认引脚
// 以下为串口3的一组映射引脚不允许映射引脚混用。
// 重映射
UART3_MAP1_TX_C10 = 0x2100 | C10,
UART3_MAP1_RX_C11 = 0x2100 | C11,
// 以下为串口3的一组映射引脚不允许映射引脚混用。
// 完全映射
UART3_MAP2_TX_D8 = 0x2300 | D8 ,
UART3_MAP2_RX_D9 = 0x2300 | D9 ,
//----------UART4-----------//
// 以下为串口4的一组映射引脚不允许映射引脚混用。
// 默认映射
UART4_MAP0_TX_C10 = 0x3000 | C10,
UART4_MAP0_RX_C11 = 0x3000 | C11,
// 以下为串口4的一组映射引脚不允许映射引脚混用。
// 重映射
UART4_MAP1_TX_B0 = 0x3100 | B0 ,
UART4_MAP1_RX_B1 = 0x3100 | B1 ,
// 以下为串口4的一组映射引脚不允许映射引脚混用。
// 完全映射
UART4_MAP3_TX_E0 = 0x3300 | E0 ,
UART4_MAP3_RX_E1 = 0x3300 | E1 ,
//----------UART5-----------//
// 以下为串口5的一组映射引脚不允许映射引脚混用。
// 默认映射
UART5_MAP0_TX_C12 = 0x4000 | C12,
UART5_MAP0_RX_D2 = 0x4000 | D2,
// 以下为串口5的一组映射引脚不允许映射引脚混用。
// 重映射
UART5_MAP1_TX_B4 = 0x4100 | B4,
UART5_MAP1_RX_B5 = 0x4100 | B5,
// 以下为串口5的一组映射引脚不允许映射引脚混用。
// 完全映射
UART5_MAP3_TX_E8 = 0x4300 | E8,
UART5_MAP3_RX_E9 = 0x4300 | E9,
//----------UART6-----------//
// 以下为串口6的一组映射引脚不允许映射引脚混用。
// 默认映射
UART6_MAP0_TX_C0 = 0x5000 | C0 ,
UART6_MAP0_RX_C1 = 0x5000 | C1 ,
// 以下为串口6的一组映射引脚不允许映射引脚混用。
// 重映射
UART6_MAP1_TX_B8 = 0x5100 | B8 ,
UART6_MAP1_RX_B9 = 0x5100 | B9 ,
// 以下为串口6的一组映射引脚不允许映射引脚混用。
// 完全映射
UART6_MAP3_TX_E10 = 0x5300 | E10,
UART6_MAP3_RX_E11 = 0x5300 | E11,
//----------UART7-----------//
// 以下为串口7的一组映射引脚不允许映射引脚混用。
// 默认映射
UART7_MAP0_TX_C2 = 0x6000 | C2 ,
UART7_MAP0_RX_C3 = 0x6000 | C3 ,
// 以下为串口7的一组映射引脚不允许映射引脚混用。
// 重映射
UART7_MAP1_TX_A6 = 0x6100 | A6 ,
UART7_MAP1_RX_A7 = 0x6100 | A7 ,
// 以下为串口7的一组映射引脚不允许映射引脚混用。
// 完全映射
UART7_MAP3_TX_E12 = 0x6300 | E12,
UART7_MAP3_RX_E13 = 0x6300 | E13,
//----------UART8-----------//
// 以下为串口8的一组映射引脚不允许映射引脚混用。
// 默认映射
UART8_MAP0_TX_C4 = 0x7000 | C4 ,
UART8_MAP0_RX_C5 = 0x7000 | C5 ,
// 以下为串口8的一组映射引脚不允许映射引脚混用。
// 重映射
UART8_MAP1_TX_A14 = 0x7100 | A14,
UART8_MAP1_RX_A15 = 0x7100 | A15,
// 以下为串口8的一组映射引脚不允许映射引脚混用。
// 完全映射
UART8_MAP3_TX_E14 = 0x7300 | E14,
UART8_MAP3_RX_E15 = 0x7300 | E15,
}uart_pin_enum;
typedef enum// 此枚举定义不允许用户修改
{
UART_1,
UART_2,
UART_3,
UART_4,
UART_5,
UART_6,
UART_7,
UART_8,
}uart_index_enum;
extern const uint32 uart_index[];
void uart_write_byte (uart_index_enum uart_n, const uint8 dat);
void uart_write_buffer (uart_index_enum uart_n, const uint8 *buff, uint32 len);
void uart_write_string (uart_index_enum uart_n, const char *str);
uint8 uart_read_byte (uart_index_enum uartn);
uint8 uart_query_byte (uart_index_enum uartn, uint8 *dat);
void uart_tx_interrupt (uart_index_enum uart_n, uint8 status);
void uart_rx_interrupt (uart_index_enum uart_n, uint8 status);
void uart_init (uart_index_enum uart_n, uint32 baud, uart_pin_enum tx_pin, uart_pin_enum rx_pin);
#endif

View File

@@ -0,0 +1,118 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_usb_cdc
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "ch32v30x.h"
#include "zf_driver_delay.h"
#include "zf_driver_usb_cdc.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 USB_CDC发送一个 包
// 参数说明 *p 要发送的数据指针
// 参数说明 length 发送多少个数据( length 需要小于64)
// 返回参数 void
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void cdc_send_pack(const uint8 *p, uint32 length)
{
uint32 i = 0;
for(i=0; i<length; i++)
{
pEP2_IN_DataBuf[i] = p[i];
}
DevEP2_IN_Deal(length);
//等待发送完成
while(!(USBOTG_FS->UEP2_TX_CTRL&USBHD_UEP_T_RES1));
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
// 00: DATA0 or DATA1 then expecting ACK (ready)
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
// 10: NAK (busy)
// 11: TALL (error)
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 发送图像数据到上位机
// 参数说明 *image 图像数组
// 参数说明 length 发送多少个数据
// 返回参数 void
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void camera_send_image_usb_cdc(const uint8 *image, uint32 length)
{
uint8 send_buffer[4] = {0x00,0xff,0x01,0x01};
cdc_send_pack(send_buffer, 4);
while(length)
{
if(length >= 63)
{
cdc_send_pack(image, 63);
image += 63;
length -= 63;
}
else
{
cdc_send_pack(image, length);
length = 0;
}
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 USB设备全速设备初始化
// 参数说明 void 空
// 返回参数 void
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void usb_cdc_init( void )
{
// 端点缓冲区初始化
pEP0_RAM_Addr = EP0_DatabufHD;
pEP1_RAM_Addr = EP1_DatabufHD;
pEP2_RAM_Addr = EP2_DatabufHD;
// 使能usb时钟
USBOTG_RCC_Init();
system_delay_ms(100);
// usb设备初始化
USBDeviceInit();
EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
// 使能usb中断
NVIC_EnableIRQ(OTG_FS_IRQn);
}

View File

@@ -0,0 +1,45 @@
/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_driver_usb_cdc
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#ifndef _zf_driver_usb_cdc_h
#define _zf_driver_usb_cdc_h
#include "ch32v30x_usbotg_device.h"
void cdc_send_pack(const uint8 *p, uint32 length);
void camera_send_image_usb_cdc(const uint8 *image, uint32 length);
void usb_cdc_init( void );
#endif