Browse Source

first commit

阿衰0110 8 months ago
commit
1a65c03e88
22 changed files with 1881 additions and 0 deletions
  1. 4 0
      README.md
  2. 79 0
      src/adc.c
  3. 92 0
      src/adc.h
  4. 57 0
      src/clk.c
  5. 54 0
      src/clk.h
  6. 65 0
      src/common.h
  7. 114 0
      src/dac.c
  8. 76 0
      src/dac.h
  9. 54 0
      src/fvr.c
  10. 49 0
      src/fvr.h
  11. 313 0
      src/gpio.c
  12. 64 0
      src/gpio.h
  13. 169 0
      src/iic.c
  14. 58 0
      src/iic.h
  15. 61 0
      src/psmc.c
  16. 130 0
      src/psmc.h
  17. 77 0
      src/spi.c
  18. 62 0
      src/spi.h
  19. 76 0
      src/timer0.c
  20. 44 0
      src/timer0.h
  21. 117 0
      src/timer1.c
  22. 66 0
      src/timer1.h

+ 4 - 0
README.md

@@ -0,0 +1,4 @@
+# pic16f1788_9_driver
+
+适用于PIC16(L)F1788, PIC16(L)F1789
+部分封装,学习使用

+ 79 - 0
src/adc.c

@@ -0,0 +1,79 @@
+/**
+  ******************************************************************************
+  * @file    adc.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-27
+  * @brief   adc驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-25    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "adc.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  adc初始化
+  * @param  config : adc配置参数结构体
+  * @retval None
+  */
+void adc_init(adc_config_t config)
+{
+    ADRESH = 0;
+    ADRESL = 0;
+    ADCON0 = (config.resultMode << 7) | (config.positiveCh << 2);
+    ADCON1 = (config.resultFormat << 7) | (config.clkSource << 4) | (config.negativeVoltage << 2) | config.positiveVoltage;
+    ADCON2 = (config.autoConvert << 4) | config.negativeCh;
+    
+    ADC_CMD(0);
+}
+
+/**
+  * @brief  adc取消初始化(恢复缺省)
+  * @param  None
+  * @retval None
+  */
+void adc_de_init(void)
+{
+    ADRESH = 0;
+    ADRESL = 0;
+    ADCON0 = 0;
+    ADCON1 = 0;
+    ADCON2 = 0;
+}
+
+/**
+  * @brief  adc转换
+  * @param  positiveCh : adc输入通道 @ref adc_chs
+  * @retval adc采样值
+  */
+uint16_t adc_convert(uint8_t positiveCh)
+{
+    uint8_t cnt = 1;
+    
+    ADCON0bits.CHS = positiveCh; /* 设置正差分输入通道 */
+    ADC_CMD(1);
+    while(cnt--); /* 使能adc后延时一段时间使充电完全 一般为几微秒 */
+    ADGO = 1;
+    while(ADGO == 1);
+    
+    return ((ADRESH << 8) | ADRESL);
+}
+

+ 92 - 0
src/adc.h

@@ -0,0 +1,92 @@
+/**
+  ******************************************************************************
+  * @file    adc.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-27
+  * @brief   adc驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __ADC_H
+#define __ADC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+#define ADC_CMD(x)                          (ADON = (x))
+    
+/* adc_clk_source */
+#define ADC_CLK_FOSC_2                      (0u) /* Fosc/2 */
+#define ADC_CLK_FOSC_4                      (4u) /* Fosc/4 */
+#define ADC_CLK_FOSC_8                      (1u)
+#define ADC_CLK_FOSC_16                     (5u)
+#define ADC_CLK_FOSC_32                     (2u)
+#define ADC_CLK_FOSC_64                     (6u)
+#define ADC_CLK_FRC                         (7u) /* adc专用Frc振荡器 */
+/* adc_chs adc_chsn  */
+#define ADC_CH_AN0                          (0u) /* AN0模拟输入引脚 */
+#define ADC_CH_AN1                          (1u)
+#define ADC_CH_AN2                          (2u)
+#define ADC_CH_AN3                          (3u)
+#define ADC_CH_AN4                          (4u)
+#define ADC_CH_AN5                          (5u)
+#define ADC_CH_AN6                          (6u)
+#define ADC_CH_AN7                          (7u)
+#define ADC_CH_AN8                          (8u)
+#define ADC_CH_AN9                          (9u)
+#define ADC_CH_AN10                         (10u)
+#define ADC_CH_AN11                         (11u)
+#define ADC_CH_AN12                         (12u)
+#define ADC_CH_AN13                         (13u)
+#define ADC_N_CH_NV                         (15u) /* 负差分输入由负参考电压提供 */
+/* adc_result_mode */
+#define ADC_RESULT_12b                      (0u) /* 12位结果 */
+#define ADC_RESULT_10b                      (1u) /* 10位结果 */
+/* adc_result_format */
+#define ADC_FORMAT_SYMBOL                   (0u) /* 符号数值 */
+#define ADC_FORMAT_BIN                      (1u) /* 二进制补码 */
+/* adc_positive_voltage */
+#define ADC_PV_VDD                          (0u) /* 正参考电压选择Vdd */
+#define ADC_PV_VREF                         (1u) /* 正参考电压选择Vref+ */
+#define ADC_PV_FVR                          (3u) /* 正参考电压选择FVR缓冲器1 */
+/* adc_negative_voltage */
+#define ADC_NV_VSS                          (0u) /* 负参考电压选择Vss */
+#define ADC_NV_VREF                         (1u) /* 负参考电压选择Vref- */
+/* adc_auto_convert */
+#define ADC_AUTO_CLOSE                      (0u)
+#define ADC_AUTO_CCP1                       (1u)
+/* adc_chsn */
+    
+/* 类型定义-------------------------------------------------------------------*/
+typedef struct adc_config {
+    uint8_t clkSource : 3; /* adc时钟源选择位 @ref adc_clk_source */
+    uint8_t positiveCh : 5; /* adc正差分输入通道选择位 @ref adc_chs */
+    uint8_t resultFormat : 1; /* adc结果格式选择位 @ref adc_result_format */
+    uint8_t resultMode : 1; /* adc结果模式位 @ref adc_result_mode */
+    uint8_t positiveVoltage : 2; /* adc正参考电压配置位 @ref adc_positive_voltage */
+    uint8_t negativeVoltage : 1; /* adc负参考电压配置位 @ref adc_negative_voltage */
+    uint8_t autoConvert : 4; /* adc自动转换触发源选择位 @ref adc_auto_convert */
+    uint8_t negativeCh : 4; /* adc负差分输入通道选择位 @ref adc_chsn */
+} adc_config_t;
+    
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void adc_init(adc_config_t config);
+uint16_t adc_convert(uint8_t positiveCh);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* adc.h */

+ 57 - 0
src/clk.c

@@ -0,0 +1,57 @@
+/**
+  ******************************************************************************
+  * @file    clk.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-19
+  * @brief   clk驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-19    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "clk.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+#define CLK_IN_OUT              (0u) /* 使用内部还是外部时钟源 0:内部  1:外部 */
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  clk初始化
+  * @param  clkFreq : 时钟频率
+  * @retval None
+  */
+void clk_init(uint8_t clkFreq)
+{
+#if CLK_IN_OUT
+    SPLLEN = 1;
+    OSCCONbits.IRCF = 0;
+    OSCCONbits.SCS = 0;
+#else
+    SPLLEN = 0;
+    OSCCONbits.IRCF = clkFreq;
+    OSCCONbits.SCS = 0x2;
+#endif
+}
+
+void clk_delay(uint16_t delay)
+{
+    while(delay--)
+    {
+        CLRWDT();
+    }
+}

+ 54 - 0
src/clk.h

@@ -0,0 +1,54 @@
+/**
+  ******************************************************************************
+  * @file    clk.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-19
+  * @brief   clk驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __CLK_H
+#define __CLK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+/* 内部振荡器频率选择 */
+#define OSC_31K_LF                  (0x0) /* 31KHz LF */
+#define OSC_31_25K_MF               (0x2) /* 31.25KHz MF */
+#define OSC_31_25K_HF               (0x3) /* 31.25KHz HF */
+#define OSC_62_5K_MF                (0x4) /* 62.5KHz MF */
+#define OSC_125K_MF                 (0x5) /* 125KHz MF */
+#define OSC_250K_MF                 (0x6) /* 250KHz MF */
+#define OSC_500K_MF                 (0x7) /* 500KHz MF 复位时的默认值 */
+#define OSC_125K_HF                 (0x8) /* 125KHz HF */
+#define OSC_250K_HF                 (0x9) /* 250KHz HF */
+#define OSC_500K_HF                 (0xA) /* 500KHz HF */
+#define OSC_1M_HF                   (0xB) /* 1MHz HF */
+#define OSC_2M_HF                   (0xC) /* 2MHz HF */
+#define OSC_4M_HF                   (0xD) /* 4MHz HF */
+#define OSC_8M_HF                   (0xE) /* 8MHz或32MHz(4xPLL使能) HF */
+#define OSC_16M_HF                  (0xF) /* 16MHz或32MHz(4xPLL使能) HF */
+    
+/* 类型定义-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+    
+/* 函数原型-------------------------------------------------------------------*/
+void clk_init(uint8_t clkFreq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* clk.h */

+ 65 - 0
src/common.h

@@ -0,0 +1,65 @@
+/**
+  ******************************************************************************
+  * @file    common.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-05
+  * @brief   驱动公共头文件,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __COMMON_H
+#define __COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include <xc.h>
+#include <stdint.h>
+
+/* 宏定义---------------------------------------------------------------------*/
+/* 选择当前MCU型号 */
+#define MCU_PIC16F1788                          (0u)
+#define MCU_PIC16F1789                          (1u)
+#define MCU_VERSION                             (MCU_PIC16F1789)
+    
+/* 全局中断开关 */
+#define ENABLE_GLOBAL_INT()                     (GIE = 1, PEIE = 1)
+#define DISABLE_GLOBAL_INT()                    (GIE = 0, PEIE = 0)
+    
+    
+/* 置位 BIT_SET(0x10,0)=0x11 */
+#ifndef BIT_SET
+  #define BIT_SET(val, bitx)                    ((val) | (1u << (bitx)))
+#endif
+/* 复位 BIT_RESET(0x11,0)=0x10 */
+#ifndef BIT_RESET
+  #define BIT_RESET(val, bitx)                  ((val) & ~(1u << (bitx)))
+#endif
+/* 读取位 BIT_READ(0x11,4)=0x10 */
+#ifndef BIT_READ
+  #define BIT_READ(val, bitx)                   ((val) & (1u << (bitx)))
+#endif
+/* 翻转位 BIT_TOGGLE(0x10,0)=0x11 */
+#ifndef BIT_TOGGLE
+  #define BIT_TOGGLE(val, bitx)                 ((val) ^ (1u << (bitx)))
+#endif
+    
+/* 类型定义-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* common.h */

+ 114 - 0
src/dac.c

@@ -0,0 +1,114 @@
+/**
+  ******************************************************************************
+  * @file    dac.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-12
+  * @brief   dac驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-12    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "dac.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/* DAC1OUT1输出举例
+    dac_config_t dacConfig;
+    dacConfig.outCh = DAC_OUT_1_ON_2_OFF;
+    dacConfig.pss = DAC_PSS_VDD;
+    dacConfig.nss = DAC_NSS_VSS;
+    dac_init(DAC1, dacConfig);
+    dac_set_value(DAC1, 0x7F);
+    dac_cmd(DAC1, 1);
+ */
+
+/**
+  * @brief  dac初始化
+  * @param  dacx   : dac通道 @ref dacx
+  * @param  config : dac配置参数
+  * @retval None
+  */
+void dac_init(uint8_t dacx, dac_config_t config)
+{
+    uint8_t tmp;
+    
+    if(DAC1 != dacx) { config.nss = DAC_NSS_VSS; }
+    tmp = (config.outCh << 4) | (config.pss << 2) | (config.nss);
+    switch(dacx)
+    {
+        case DAC1: DAC1CON0 = tmp; break;
+        case DAC2: DAC2CON0 = tmp; break;
+        case DAC3: DAC3CON0 = tmp; break;
+        case DAC4: DAC4CON0 = tmp; break;
+    }
+}
+
+/**
+  * @brief  dac取消初始化(恢复缺省)
+  * @param  dacx : dac通道 @ref dacx
+  * @retval None
+  */
+void dac_de_init(uint8_t dacx)
+{
+    switch(dacx)
+    {
+        case DAC1: DAC1CON0 = 0; break;
+        case DAC2: DAC2CON0 = 0; break;
+        case DAC3: DAC3CON0 = 0; break;
+        case DAC4: DAC4CON0 = 0; break;
+    }
+}
+
+/**
+  * @brief  dac控制
+  * @param  dacx  : dac通道 @ref dacx
+  * @param  state : 0关闭 1开启
+  * @retval None
+  */
+void dac_cmd(uint8_t dacx, uint8_t state)
+{
+    switch(dacx)
+    {
+        case DAC1: DAC1EN = state; break;
+        case DAC2: DAC2EN = state; break;
+        case DAC3: DAC3EN = state; break;
+        case DAC4: DAC4EN = state; break;
+    }
+}
+
+/**
+  * @brief  dac设置值
+  * @param  dacx  : dac通道 @ref dacx
+  * @param  value : 0~255
+  * @retval None
+  */
+void dac_set_value(uint8_t dacx, uint8_t value)
+{
+    switch(dacx)
+    {
+        case DAC1: DAC1CON1 = value; break;
+        case DAC2: DAC2CON1 = value & 0x1F; break;
+        case DAC3: DAC3CON1 = value & 0x1F; break;
+        case DAC4: DAC4CON1 = value & 0x1F; break;
+    }
+}
+
+
+

+ 76 - 0
src/dac.h

@@ -0,0 +1,76 @@
+/**
+  ******************************************************************************
+  * @file    dac.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-12
+  * @brief   dac驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __DAC_H
+#define __DAC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+#define DAC1_CMD(x)                         (DAC1EN = (x)) /* DAC1开关 0:关闭 1:使能 */
+#define DAC2_CMD(x)                         (DAC2EN = (x)) /* DAC2开关 0:关闭 1:使能 */
+#define DAC3_CMD(x)                         (DAC3EN = (x)) /* DAC3开关 0:关闭 1:使能 */
+#define DAC4_CMD(x)                         (DAC4EN = (x)) /* DAC4开关 0:关闭 1:使能 */
+    
+#define DAC1_SET_VALUE(x)                   (DAC1CON1 = (x)) /* 设置DAC1输出 */
+#define DAC2_SET_VALUE(x)                   (DAC2CON1 = (x)) /* 设置DAC2输出 */
+#define DAC3_SET_VALUE(x)                   (DAC3CON1 = (x)) /* 设置DAC3输出 */
+#define DAC4_SET_VALUE(x)                   (DAC4CON1 = (x)) /* 设置DAC4输出 */
+    
+/* dacx */
+#define DAC1                                (0u) /* 8位DAC */
+#define DAC2                                (1u) /* 5位DAC */
+#define DAC3                                (2u) /* 5位DAC */
+#define DAC4                                (3u) /* 5位DAC */
+/* dac_out_channel DAC输出引脚选择 */
+#define DAC_OUT_ALL_OFF                     (0u) /* DACOUT1 DACOUT2引脚输出全关 */
+#define DAC_OUT_1_ON_2_OFF                  (2u) /* DACOUT1引脚输出打开 DACOUT2引脚输出关闭 */
+#define DAC_OUT_2_ON_1_OFF                  (1u) /* DACOUT2引脚输出打开 DACOUT1引脚输出关闭 */
+#define DAC_OUT_ALL_ON                      (3u) /* DACOUT1 DACOUT2引脚输出全开 */
+/* positive_reference DAC正参考电压选择 */    
+#define DAC_PSS_VDD                         (0u) /* DAC正参考选择Vdd */
+#define DAC_PSS_VREF                        (1u) /* DAC正参考选择Vref+引脚 */
+#define DAC_PSS_FVR2                        (2u) /* DAC正参考选择FVR缓冲器2输出 */
+#define DAC_PSS_RESERVE                     (3u) /* 保留,不使用 */
+/* negative_reference DAC负参考电压选择(5位DAC负参考默认Vss不可更改) */   
+#define DAC_NSS_VSS                         (0u) /* DAC负参考选择Vss */
+#define DAC_NSS_VREF                        (1u) /* DAC负参考选择Vref-引脚 */
+    
+/* 类型定义-------------------------------------------------------------------*/
+typedef struct dac_config {
+    uint8_t outCh : 3; /* @ref dac_out_channel */
+    uint8_t pss : 3;   /* @ref positive_reference */
+    uint8_t nss : 2;   /* @ref negative_reference */
+}dac_config_t;
+    
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void dac_init(uint8_t dacx, dac_config_t _config);
+void dac_de_init(uint8_t dacx);
+
+void dac_cmd(uint8_t dacx, uint8_t state);
+
+void dac_set_value(uint8_t dacx, uint8_t value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* dac.h */

+ 54 - 0
src/fvr.c

@@ -0,0 +1,54 @@
+/**
+  ******************************************************************************
+  * @file    fvr.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-18
+  * @brief   fvr驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-18    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "fvr.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  fvr初始化
+  * @param  config : fvr配置结构体
+  * @retval None
+  */
+void fvr_init(fvr_config_t config)
+{
+    FVRCONbits.CDAFVR = config.dacVoltage; /* 比较器和DAC固定参考电压选择位 */
+    FVRCONbits.ADFVR = config.adcVoltage; /* ADC固定参考电压选择位 */
+    
+    FVR_CMD(1); /* 使能FVR输出 */
+    while(FVRRDY == 0); /* 等待输出就绪 */
+}
+
+/**
+  * @brief  fvr取消初始化(恢复缺省)
+  * @param  None
+  * @retval None
+  */
+void fvr_de_init(void)
+{
+    FVRCON = 0;
+}

+ 49 - 0
src/fvr.h

@@ -0,0 +1,49 @@
+/**
+  ******************************************************************************
+  * @file    fvr.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-18
+  * @brief   fvr驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __FVR_H
+#define __FVR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+#define FVR_CMD(x)                              (FVREN = (x)) /* FVR开关 0:关闭 1:使能 */
+/* fvr_voltage 固定参考电压选择 */ 
+#define FVR_VOL_CLOSE                           (0u) /* 固定参考电压输出关闭 */
+#define FVR_VOL_1X                              (1u) /* 固定参考电压输出1.024V */
+#define FVR_VOL_2X                              (2u) /* 固定参考电压输出2.048V */
+#define FVR_VOL_4X                              (3u) /* 固定参考电压输出4.096V */
+
+/* 类型定义-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+typedef struct fvr_config {
+    uint8_t dacVoltage : 4; /* 比较器和DAC固定参考电压选择 @ref fvr_voltage */ 
+    uint8_t adcVoltage : 4; /* ADC固定参考电压选择 @ref fvr_voltage */
+} fvr_config_t;
+    
+/* 函数原型-------------------------------------------------------------------*/
+void fvr_init(fvr_config_t config);
+void fvr_de_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fvr.h */

+ 313 - 0
src/gpio.c

@@ -0,0 +1,313 @@
+/**
+  ******************************************************************************
+  * @file    gpio.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-09
+  * @brief   gpio驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-09    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "gpio.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/* RC5引脚推挽输出高电平举例
+    io_config_t ioConfig;
+    ioConfig.mode = GPIO_MODE_OUT_PP;
+    ioConfig.speed = GPIO_SPEED_HIGH;
+    gpio_init(GPIO_PORTC, 5, ioConfig);
+    gpio_write(GPIO_PORTC, 5, 1);
+ */
+
+/**
+  * @brief  gpio初始化
+  * @param  port   : 端口 @ref GPIO_PORT
+  * @param  pin    : 引脚(0~7)
+  * @param  config : io参数 @ref GPIO_CONFIG
+  * @retval None
+  */
+void gpio_init(uint8_t port, uint8_t pin, io_config_t config)
+{
+    switch(port)
+    {
+        case GPIO_PORTA:
+            ANSELA = BIT_RESET(ANSELA, pin);
+            if(config.mode > GPIO_MODE_ANALOG_IN)
+            {
+                TRISA = BIT_RESET(TRISA, pin);
+                if(config.mode == GPIO_MODE_OUT_PP)
+                {
+                    ODCONA = BIT_RESET(ODCONA, pin);
+                }
+                else
+                {
+                    ODCONA = BIT_SET(ODCONA, pin);
+                }
+            }
+            else
+            {
+                TRISA = BIT_SET(TRISA, pin);
+                if(config.mode == GPIO_MODE_IN)
+                {
+                    WPUA = BIT_RESET(WPUA, pin);
+                }
+                else if(config.mode == GPIO_MODE_IPU)
+                {
+                    WPUA = BIT_SET(WPUA, pin);
+                }
+                else
+                {
+                    ANSELA = BIT_SET(ANSELA, pin);
+                }
+            }
+            if(config.speed == GPIO_SPEED_HIGH)
+            {
+                SLRCONA = BIT_RESET(SLRCONA, pin);
+            }
+            else
+            {
+                SLRCONA = BIT_SET(SLRCONA, pin);
+            }
+            break;
+        case GPIO_PORTB:
+            ANSELB = BIT_RESET(ANSELB, pin);
+            if(config.mode > GPIO_MODE_ANALOG_IN)
+            {
+                TRISB = BIT_RESET(TRISB, pin);
+                if(config.mode == GPIO_MODE_OUT_PP)
+                {
+                    ODCONB = BIT_RESET(ODCONB, pin);
+                }
+                else
+                {
+                    ODCONB = BIT_SET(ODCONB, pin);
+                }
+            }
+            else
+            {
+                TRISB = BIT_SET(TRISB, pin);
+                if(config.mode == GPIO_MODE_IN)
+                {
+                    WPUB = BIT_RESET(WPUB, pin);
+                }
+                else if(config.mode == GPIO_MODE_IPU)
+                {
+                    WPUB = BIT_SET(WPUB, pin);
+                }
+                else
+                {
+                    ANSELB = BIT_SET(ANSELB, pin);
+                }
+            }
+            if(config.speed == GPIO_SPEED_HIGH)
+            {
+                SLRCONB = BIT_RESET(SLRCONB, pin);
+            }
+            else
+            {
+                SLRCONB = BIT_SET(SLRCONB, pin);
+            }
+            break;
+        case GPIO_PORTC:
+            ANSELC = BIT_RESET(ANSELC, pin);
+            if(config.mode > GPIO_MODE_ANALOG_IN)
+            {
+                TRISC = BIT_RESET(TRISC, pin);
+                if(config.mode == GPIO_MODE_OUT_PP)
+                {
+                    ODCONC = BIT_RESET(ODCONC, pin);
+                }
+                else
+                {
+                    ODCONC = BIT_SET(ODCONC, pin);
+                }
+            }
+            else
+            {
+                TRISC = BIT_SET(TRISC, pin);
+                if(config.mode == GPIO_MODE_IN)
+                {
+                    WPUC = BIT_RESET(WPUC, pin);
+                }
+                else if(config.mode == GPIO_MODE_IPU)
+                {
+                    WPUC = BIT_SET(WPUC, pin);
+                }
+                else
+                {
+                    ANSELC = BIT_SET(ANSELC, pin);
+                }
+            }
+            if(config.speed == GPIO_SPEED_HIGH)
+            {
+                SLRCONC = BIT_RESET(SLRCONC, pin);
+            }
+            else
+            {
+                SLRCONC = BIT_SET(SLRCONC, pin);
+            }
+            break;
+#if (MCU_VERSION == MCU_PIC16F1789)
+        case GPIO_PORTD:
+            ANSELD = BIT_RESET(ANSELD, pin);
+            if(config.mode > GPIO_MODE_ANALOG_IN)
+            {
+                TRISD = BIT_RESET(TRISD, pin);
+                if(config.mode == GPIO_MODE_OUT_PP)
+                {
+                    ODCOND = BIT_RESET(ODCOND, pin);
+                }
+                else
+                {
+                    ODCOND = BIT_SET(ODCOND, pin);
+                }
+            }
+            else
+            {
+                TRISD = BIT_SET(TRISD, pin);
+                if(config.mode == GPIO_MODE_IN)
+                {
+                    WPUD = BIT_RESET(WPUD, pin);
+                }
+                else if(config.mode == GPIO_MODE_IPU)
+                {
+                    WPUD = BIT_SET(WPUD, pin);
+                }
+                else
+                {
+                    ANSELD = BIT_SET(ANSELD, pin);
+                }
+            }
+            if(config.speed == GPIO_SPEED_HIGH)
+            {
+                SLRCOND = BIT_RESET(SLRCOND, pin);
+            }
+            else
+            {
+                SLRCOND = BIT_SET(SLRCOND, pin);
+            }
+            break;
+#endif
+        case GPIO_PORTE:
+//            ANSELE = BIT_RESET(ANSELE, pin);
+            if(config.mode > GPIO_MODE_ANALOG_IN)
+            {
+                TRISE = BIT_RESET(TRISE, pin);
+//                if(config.mode == GPIO_MODE_OUT_PP)
+//                {
+//                    ODCONE = BIT_RESET(ODCONE, pin);
+//                }
+//                else
+//                {
+//                    ODCONE = BIT_SET(ODCONE, pin);
+//                }
+            }
+            else
+            {
+                TRISE = BIT_SET(TRISE, pin);
+                if(config.mode == GPIO_MODE_IN)
+                {
+                    WPUE = BIT_RESET(WPUE, pin);
+                }
+                else if(config.mode == GPIO_MODE_IPU)
+                {
+                    WPUE = BIT_SET(WPUE, pin);
+                }
+                else
+                {
+//                    ANSELE = BIT_SET(ANSELE, pin);
+                }
+            }
+//            if(config.speed == GPIO_SPEED_HIGH)
+//            {
+//                SLRCONE = BIT_RESET(SLRCONE, pin);
+//            }
+//            else
+//            {
+//                SLRCONE = BIT_SET(SLRCONE, pin);
+//            }
+            break;
+    }
+}
+/**
+  * @brief  gpio写输出电平
+  * @param  port  : 端口 @ref GPIO_PORT
+  * @param  pin   : 引脚(0~7)
+  * @param  level : 电平(0或1)
+  * @retval None
+  */
+void gpio_write(uint8_t port, uint8_t pin, uint8_t level)
+{
+    switch(port)
+    {
+        case GPIO_PORTA: PORTA = (level != 0) ? BIT_SET(PORTA, pin) : BIT_RESET(PORTA, pin); break;
+        case GPIO_PORTB: PORTB = (level != 0) ? BIT_SET(PORTB, pin) : BIT_RESET(PORTB, pin); break;
+        case GPIO_PORTC: PORTC = (level != 0) ? BIT_SET(PORTC, pin) : BIT_RESET(PORTC, pin); break;
+#if (MCU_VERSION == MCU_PIC16F1789)
+        case GPIO_PORTD: PORTD = (level != 0) ? BIT_SET(PORTD, pin) : BIT_RESET(PORTD, pin); break;
+#endif
+        case GPIO_PORTE: PORTE = (level != 0) ? BIT_SET(PORTE, pin) : BIT_RESET(PORTE, pin); break;
+    }
+}
+/**
+  * @brief  gpio读输入电平
+  * @param  port  : 端口 @ref GPIO_PORT
+  * @param  pin   : 引脚(0~7)
+  * @retval 电平(0或1)
+  */
+uint8_t gpio_read(uint8_t port, uint8_t pin)
+{
+    uint8_t level;
+    
+    switch(port)
+    {
+        case GPIO_PORTA: level = BIT_READ(PORTA, pin); break;
+        case GPIO_PORTB: level = BIT_READ(PORTB, pin); break;
+        case GPIO_PORTC: level = BIT_READ(PORTC, pin); break;
+#if (MCU_VERSION == MCU_PIC16F1789)
+        case GPIO_PORTD: level = BIT_READ(PORTD, pin); break;
+#endif
+        case GPIO_PORTE: level = BIT_READ(PORTE, pin); break;
+    }
+    level = (level > 0) ? 1u : 0u;
+    
+    return level;
+}
+/**
+  * @brief  gpio输出电平翻转
+  * @param  port  : 端口 @ref GPIO_PORT
+  * @param  pin   : 引脚(0~7)
+  * @retval None
+  */
+void gpio_toggle(uint8_t port, uint8_t pin)
+{
+    switch(port)
+    {
+        case GPIO_PORTA: PORTA = BIT_TOGGLE(PORTA, pin); break;
+        case GPIO_PORTB: PORTB = BIT_TOGGLE(PORTB, pin); break;
+        case GPIO_PORTC: PORTC = BIT_TOGGLE(PORTC, pin); break;
+#if (MCU_VERSION == MCU_PIC16F1789)
+        case GPIO_PORTD: PORTD = BIT_TOGGLE(PORTD, pin); break;
+#endif
+        case GPIO_PORTE: PORTE = BIT_TOGGLE(PORTE, pin); break;
+    }
+}
+

+ 64 - 0
src/gpio.h

@@ -0,0 +1,64 @@
+/**
+  ******************************************************************************
+  * @file    gpio.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-09
+  * @brief   gpio驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __GPIO_H
+#define __GPIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+/* gpio_port gpio端口 */
+#define GPIO_PORTA                  (0x0)
+#define GPIO_PORTB                  (0x1)
+#define GPIO_PORTC                  (0x2)
+#define GPIO_PORTD                  (0x3)
+#define GPIO_PORTE                  (0x4)
+
+/* gpio_mode gpio模式 */
+#define GPIO_MODE_IN                (0x0)
+#define GPIO_MODE_IPU               (0x1)
+#define GPIO_MODE_ANALOG_IN         (0x2)
+#define GPIO_MODE_OUT_PP            (0x3)
+#define GPIO_MODE_OUT_OD            (0x4)
+    
+/* gpio_speed gpio速率 */
+#define GPIO_SPEED_HIGH             (0x0) /* 高速 */
+#define GPIO_SPEED_LOW              (0x1) /* 低速 */
+    
+/* 类型定义-------------------------------------------------------------------*/
+/* gpio_config struct */
+typedef struct io_config {
+    uint8_t mode : 6;  /* @ref gpio_mode */
+    uint8_t speed : 2; /* @ref gpio_speed */
+} io_config_t;
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void gpio_init(uint8_t port, uint8_t pin, io_config_t config);
+
+void gpio_write(uint8_t port, uint8_t pin, uint8_t level);
+uint8_t gpio_read(uint8_t port, uint8_t pin);
+void gpio_toggle(uint8_t port, uint8_t pin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gpio.h */

+ 169 - 0
src/iic.c

@@ -0,0 +1,169 @@
+/**
+  ******************************************************************************
+  * @file    iic.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-16
+  * @brief   iic驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-16    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "iic.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  iic初始化(RC3-SCL RC4-SDA)
+  * @param  config : 参数结构体
+  * @retval None
+  */
+void iic_init(iic_config_t config)
+{
+    /* 修改两个引脚为输入 */
+    TRISC3 = 1;
+    TRISC4 = 1;
+    SSP1CON1bits.SSPM = config.mode; /* MSSP的模式选择位 详见手册 */
+    SMP = 1; /* 禁用IO速度限制 */
+    SSPADD = config.freqDiv - 1; /* MSSP波特率发生寄存器 */
+    SSP1IE = 0; /* 关闭中断 */
+    SSP1IF = 0;
+    SSPEN = 1; /* 使能MSSP */
+}
+
+/**
+  * @brief  iic取消初始化(恢复缺省)
+  * @param  None
+  * @retval None
+  */
+void iic_de_init(void)
+{
+    SSP1CON1bits.SSPM = 0;
+    SMP = 0;
+    SSPADD = 0;
+    SSPEN = 0;
+}
+
+/**
+  * @brief  iic启动
+  * @param  None
+  * @retval None
+  */
+inline void iic_start(void)
+{
+    SEN = 1; /* iic启动 */
+    while(SEN == 1);
+    SSP1IF = 0;
+}
+
+/**
+  * @brief  iic重新启动
+  * @param  None
+  * @retval None
+  */
+inline void iic_restart(void)
+{
+    RSEN = 1; /* iic重新启动 */
+    while(RSEN == 1);
+    SSP1IF = 0;
+}
+
+/**
+  * @brief  iic写一个字节
+  * @param  byte : 写入数据
+  * @retval None
+  */
+inline void iic_write(uint8_t byte)
+{
+    SSP1BUF = byte; /* 写数据 */
+    while(ACKSTAT == 1);
+    while(SSP1IF == 0);
+    SSP1IF = 0;
+}
+
+/**
+  * @brief  iic读一个字节
+  * @param  ack : 0:ACK  1:NAK
+  * @retval 读出数据
+  */
+inline uint8_t iic_read(uint8_t ack)
+{
+    uint8_t tmp;
+    
+    RCEN = 1; /* 接收使能 */
+    while(SSP1IF == 0);
+    SSP1IF = 0;
+    tmp = SSP1BUF; /* 数据 */
+    ACKDT = ack; /* 0:ACK  1:NAK */
+    ACKEN = 1;
+    while(SSP1IF == 0);
+    SSP1IF = 0;
+    
+    return tmp;
+}
+
+/**
+  * @brief  iic停止
+  * @param  None
+  * @retval None
+  */
+inline void iic_stop(void)
+{
+    PEN = 1; /* iic结束 */
+}
+
+/**
+  * @brief  iic写多个字节
+  * @param  addr  : 写地址
+  * @param  bytes : 写入数据缓冲区
+  * @param  len   : 要写入的数量
+  * @retval None
+  */
+void iic_write_bytes(uint8_t addr, uint8_t *bytes, uint8_t len)
+{
+    iic_start();
+    
+    iic_write(addr & 0xFE);
+    while(len--)
+    {
+        iic_write(*bytes++);
+    }
+    
+    iic_stop();
+}
+
+/**
+  * @brief  iic读多个字节
+  * @param  addr  : 读地址
+  * @param  bytes : 读出数据存储区
+  * @param  len   : 要读出的数量
+  * @retval None
+  */
+void iic_read_bytes(uint8_t addr, uint8_t *bytes, uint8_t len)
+{
+    iic_start();
+    
+    iic_write(addr | 0x01);
+    while(len--)
+    {
+        *bytes++ = iic_read(len == 1 ? 1 : 0);
+    }
+    
+    iic_stop();
+}

+ 58 - 0
src/iic.h

@@ -0,0 +1,58 @@
+/**
+  ******************************************************************************
+  * @file    iic.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-16
+  * @brief   iic驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __IIC_H
+#define __IIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+/* iic_mode iic主从模式选择 */
+#define IIC_MODE_MASTER                         (0x8) /* 主模式,时钟=Fosc/(4*(SSPADD+1)) */
+#define IIC_MODE_SLAVE_7                        (0x6) /* 从模式,7位地址 */
+#define IIC_MODE_SLAVE_10                       (0x7) /* 从模式,10位地址 */
+#define IIC_MODE_SLAVE_7_IT                     (0xE) /* 从模式,7位地址,允许启动和停止位中断 */
+#define IIC_MODE_SLAVE_10_IT                    (0xF) /* 从模式,10位地址,允许启动和停止位中断 */
+    
+/* 类型定义-------------------------------------------------------------------*/
+typedef struct iic_config {
+    uint8_t mode : 4; /* @ref iic_mode */
+    uint8_t freqDiv; /* 时钟分频 4~255 */
+} iic_config_t;
+    
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void iic_init(iic_config_t _config);
+void iic_de_init(void);
+
+inline void iic_start(void);
+inline void iic_restart(void);
+inline void iic_write(uint8_t byte);
+inline uint8_t iic_read(uint8_t ack);
+inline void iic_stop(void);
+
+void iic_write_bytes(uint8_t addr, uint8_t *bytes, uint8_t len);
+void iic_read_bytes(uint8_t addr, uint8_t *bytes, uint8_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* iic.h */

+ 61 - 0
src/psmc.c

@@ -0,0 +1,61 @@
+/**
+  ******************************************************************************
+  * @file    psmc.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-24
+  * @brief   psmc驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-22    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "psmc.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  psmc1(高级pwm)初始化
+  * @note   
+  * @param  ch : 输出的通道 @ref psmc_channel
+  * @retval None
+  */
+void psmc1_init(uint8_t ch)
+{
+    PSMC1CONbits.P1MODE = 0; /* 工作模式 0:单向PWM 1:单向互补PWM */
+    PSMC1MDL = 0; /* 调制控制 */
+    PSMC1SYNC = 0; /* 同步控制 */
+    PSMC1CLKbits.P1CPRE = 1; /* 预分频比选择位 0:1  1:2  2:4  3:8 */
+    PSMC1CLKbits.P1CSRC = 0; /* 时钟源选择位 0:Fosc  1:PLL的64MHz  2:PSMCxCLK引脚 */
+    
+    PSMC1OEN = ch; /* 输出使能控制(bit5~0:F~E)  0:无输出  1:输出有效 */
+    PSMC1POL = 0; /* 极性控制(bit5~0:F~E) 0:高电平有效  1:低电平有效 */
+    
+    P1PHST = 1; /* 基于时基匹配发生上升沿事件 0:不发生  1:发生 */
+    P1DCST = 1; /* 基于时基匹配发生下降沿事件 0:不发生  1:发生 */
+    P1PRST = 1; /* 基于时基匹配发生周期事件 0:不发生  1:发生 */
+    
+    PSMC1ASDC = 0; /* 自动关闭控制 不启用自动关闭 */
+    PSMC1ASDL = 0; /* 自动关闭输出电平选择 0:逻辑0  1:逻辑1 */
+    PSMC1ASDS = 0; /* 自动关闭源 */
+    
+    PSMC1STR0 = ch; /* PSMC转向控制0(bit5~0:F~E)  0:转向无效  1:转向有效 */
+    PSMC1STR1 = 0; /* PSMC转向控制1 */
+    
+    PSMC1_CMD(0); /* psmc1开关控制 */
+}

+ 130 - 0
src/psmc.h

@@ -0,0 +1,130 @@
+/**
+  ******************************************************************************
+  * @file    psmc.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-24
+  * @brief   psmc驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __PSMC_H
+#define __PSMC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+/* psmc_channel PSMC输出通道选择 */
+#define PSMC_CH_CLOSE                       (0x0)  /* 输出通道关闭恢复IO功能 */
+#define PSMC_CH_A                           (0x01)
+#define PSMC_CH_B                           (0x02)
+#define PSMC_CH_C                           (0x04)
+#define PSMC_CH_D                           (0x08)
+#define PSMC_CH_E                           (0x10)
+#define PSMC_CH_F                           (0x20)
+    
+#define PSMC_CNT_MAX                        (0xFFFF)
+    
+/* PSMCx开关控制 0:关闭  1:开启  */
+#define PSMC1_CMD(x)                        (PSMC1LD = (x), PSMC1EN = (x))
+#define PSMC2_CMD(x)                        (PSMC2LD = (x), PSMC2EN = (x))
+#define PSMC3_CMD(x)                        (PSMC3LD = (x), PSMC3EN = (x))
+#define PSMC4_CMD(x)                        (PSMC4LD = (x), PSMC4EN = (x))
+/* PSMCx时基计数值设置 0~0xFFFF */
+#define PSMC1_SET_TMR_CNT(val)              (PSMC1TMRL = ((val) & 0xFF), PSMC1TMRH = ((val) >> 8))
+#define PSMC2_SET_TMR_CNT(val)              (PSMC2TMRL = ((val) & 0xFF), PSMC2TMRH = ((val) >> 8))
+#define PSMC3_SET_TMR_CNT(val)              (PSMC3TMRL = ((val) & 0xFF), PSMC3TMRH = ((val) >> 8))
+#define PSMC4_SET_TMR_CNT(val)              (PSMC4TMRL = ((val) & 0xFF), PSMC4TMRH = ((val) >> 8))
+/* PSMCx相位(上升沿事件)计数值设置 0~0xFFFF */
+#define PSMC1_SET_RISE_CNT(val)             (PSMC1PHL = ((val) & 0xFF), PSMC1PHH = ((val) >> 8))
+#define PSMC2_SET_RISE_CNT(val)             (PSMC2PHL = ((val) & 0xFF), PSMC2PHH = ((val) >> 8))
+#define PSMC3_SET_RISE_CNT(val)             (PSMC3PHL = ((val) & 0xFF), PSMC3PHH = ((val) >> 8))
+#define PSMC4_SET_RISE_CNT(val)             (PSMC4PHL = ((val) & 0xFF), PSMC4PHH = ((val) >> 8))
+/* PSMCx占空比(下降沿事件)计数值设置 0~0xFFFF */
+#define PSMC1_SET_FALL_CNT(val)             (PSMC1DCL = ((val) & 0xFF), PSMC1DCH = ((val) >> 8))
+#define PSMC2_SET_FALL_CNT(val)             (PSMC2DCL = ((val) & 0xFF), PSMC2DCH = ((val) >> 8))
+#define PSMC3_SET_FALL_CNT(val)             (PSMC3DCL = ((val) & 0xFF), PSMC3DCH = ((val) >> 8))
+#define PSMC4_SET_FALL_CNT(val)             (PSMC4DCL = ((val) & 0xFF), PSMC4DCH = ((val) >> 8))
+/* PSMCx周期计数值设置 0~0xFFFF */
+#define PSMC1_SET_PERIOD_CNT(val)           (PSMC1PRL = ((val) & 0xFF), PSMC1PRH = ((val) >> 8))
+#define PSMC2_SET_PERIOD_CNT(val)           (PSMC2PRL = ((val) & 0xFF), PSMC2PRH = ((val) >> 8))
+#define PSMC3_SET_PERIOD_CNT(val)           (PSMC3PRL = ((val) & 0xFF), PSMC3PRH = ((val) >> 8))
+#define PSMC4_SET_PERIOD_CNT(val)           (PSMC4PRL = ((val) & 0xFF), PSMC4PRH = ((val) >> 8))
+/* PSMCx产生的中断控制(类似全局中断控制,它控制PSMCx下的所有中断) 0:关闭 1:开启 */
+#define PSMC1_IT_CMD(x)                     (PSMC1TIE = (x))
+#define PSMC2_IT_CMD(x)                     (PSMC2TIE = (x))
+#define PSMC3_IT_CMD(x)                     (PSMC3TIE = (x))
+#define PSMC4_IT_CMD(x)                     (PSMC4TIE = (x))
+/* PSMCx时基溢出中断控制 0:关闭 1:开启 */
+#define PSMC1_TMR_IT_CMD(x)                 (P1TOVIE = (x))
+#define PSMC2_TMR_IT_CMD(x)                 (P2TOVIE = (x))
+#define PSMC3_TMR_IT_CMD(x)                 (P3TOVIE = (x))
+#define PSMC4_TMR_IT_CMD(x)                 (P4TOVIE = (x))
+/* PSMCx相位(上升沿事件)中断控制 0:关闭 1:开启 */
+#define PSMC1_RISE_IT_CMD(x)                (P1TPHIE = (x))
+#define PSMC2_RISE_IT_CMD(x)                (P2TPHIE = (x))
+#define PSMC3_RISE_IT_CMD(x)                (P3TPHIE = (x))
+#define PSMC4_RISE_IT_CMD(x)                (P4TPHIE = (x))
+/* PSMCx占空比(下降沿事件)中断控制 0:关闭 1:开启 */
+#define PSMC1_FALL_IT_CMD(x)                (P1TDCIE = (x))
+#define PSMC2_FALL_IT_CMD(x)                (P2TDCIE = (x))
+#define PSMC3_FALL_IT_CMD(x)                (P3TDCIE = (x))
+#define PSMC4_FALL_IT_CMD(x)                (P4TDCIE = (x))
+/* PSMCx周期中断控制 0:关闭 1:开启 */
+#define PSMC1_PERIOD_IT_CMD(x)              (P1TPRIE = (x))
+#define PSMC2_PERIOD_IT_CMD(x)              (P2TPRIE = (x))
+#define PSMC3_PERIOD_IT_CMD(x)              (P3TPRIE = (x))
+#define PSMC4_PERIOD_IT_CMD(x)              (P4TPRIE = (x))
+/* PSMCx时基溢出中断标志位 */
+#define PSMC1_TMR_IT_FLAG                   P1TOVIF
+#define PSMC2_TMR_IT_FLAG                   P2TOVIF
+#define PSMC3_TMR_IT_FLAG                   P3TOVIF
+#define PSMC4_TMR_IT_FLAG                   P4TOVIF
+/* PSMCx相位(上升沿事件)中断标志位 */
+#define PSMC1_RISE_IT_FLAG                  P1TPHIF
+#define PSMC2_RISE_IT_FLAG                  P2TPHIF
+#define PSMC3_RISE_IT_FLAG                  P3TPHIF
+#define PSMC4_RISE_IT_FLAG                  P4TPHIF
+/* PSMCx占空比(下降沿事件)中断标志位 */
+#define PSMC1_FALL_IT_FLAG                  P1TDCIF
+#define PSMC2_FALL_IT_FLAG                  P2TDCIF
+#define PSMC3_FALL_IT_FLAG                  P3TDCIF
+#define PSMC4_FALL_IT_FLAG                  P4TDCIF
+/* PSMCx周期中断标志位 */
+#define PSMC1_PERIOD_IT_FLAG                P1TPRIF
+#define PSMC2_PERIOD_IT_FLAG                P2TPRIF
+#define PSMC3_PERIOD_IT_FLAG                P3TPRIF
+#define PSMC4_PERIOD_IT_FLAG                P4TPRIF
+/* PSMCx通道输出使能控制 置位的通道作为psmc输出否则是普通io @ref psmc_channel */
+#define PSMC1_OUT_EN_CTRL(ch)               (PSMC1OEN = (ch))
+#define PSMC2_OUT_EN_CTRL(ch)               (PSMC2OEN = (ch))
+#define PSMC3_OUT_EN_CTRL(ch)               (PSMC3OEN = (ch))
+#define PSMC4_OUT_EN_CTRL(ch)               (PSMC4OEN = (ch))
+/* PSMCx通道输出转向控制 置位的通道可以输出PWM否则输出无效 @ref psmc_channel */
+#define PSMC1_OUT_SW_CTRL(ch)               (PSMC1STR0 = (ch))
+#define PSMC2_OUT_SW_CTRL(ch)               (PSMC2STR0 = (ch))
+#define PSMC3_OUT_SW_CTRL(ch)               (PSMC3STR0 = (ch))
+#define PSMC4_OUT_SW_CTRL(ch)               (PSMC4STR0 = (ch))
+    
+/* 类型定义-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void psmc1_init(uint8_t ch);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* psmc.h */

+ 77 - 0
src/spi.c

@@ -0,0 +1,77 @@
+/**
+  ******************************************************************************
+  * @file    spi.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-03-14
+  * @brief   spi驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-03-14    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "spi.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  spi初始化(RC3-SCK RC4-SDI RC5-SDO)
+  * @param  None
+  * @retval None
+  */
+void spi_init(spi_config_t config)
+{
+    /* 修改对应引脚为输入输出 */
+    if(SPI_MODE_SLAVE_CS == config.mode || SPI_MODE_SLAVE == config.mode)
+    {
+        TRISC3 = 1;
+    }
+    else
+    {
+        TRISC3 = 0;
+    }
+    TRISC4 = 1;
+    TRISC5 = 0;
+    SSP1CON1bits.SSPM = config.mode; /* MSSP的模式选择位 详见手册 */
+    SMP = 0;
+    if(SPI_MODE_MASTER == config.mode)
+    {
+        SSPADD = config.freqDiv - 1; /* MSSP波特率发生寄存器 */
+    }
+    CKE = config.cpha; /* 时钟相位 */
+    CKP = config.cpol; /* 时钟极性 */
+    SSP1IE = 0; /* 关闭中断 */
+    SSP1IF = 0;
+    SSPEN = 1; /* 使能MSSP */
+}
+
+/**
+  * @brief  spi读写数据
+  * @param  byte : 写入的数据
+  * @retval 读出的数据
+  */
+uint8_t spi_rw(uint8_t byte)
+{
+    SSP1IF = 0;
+    SSP1BUF = byte;
+    while(SSP1IF == 0);
+    SSP1IF = 0;
+    
+    return SSP1BUF;
+}
+

+ 62 - 0
src/spi.h

@@ -0,0 +1,62 @@
+/**
+  ******************************************************************************
+  * @file    spi.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-03-14
+  * @brief   spi驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __SPI_H
+#define __SPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+
+#define SPI_CMD(x)                          (SSPEN = (x)) /* SPI开关 */
+    
+/* spi_mode spi模式选择 */
+#define SPI_MODE_MASTER_4                   (0x0) /* 主模式,时钟=Fosc/4 */
+#define SPI_MODE_MASTER_16                  (0x1) /* 主模式,时钟=Fosc/16 */
+#define SPI_MODE_MASTER_64                  (0x2) /* 主模式,时钟=Fosc/64 */
+#define SPI_MODE_MASTER_TMR2                (0x3) /* 主模式,时钟=TMR2输出/2 */
+#define SPI_MODE_SLAVE_CS                   (0x4) /* 从模式,时钟=SCK引脚,使能CS引脚控制 */
+#define SPI_MODE_SLAVE                      (0x5) /* 从模式,时钟=SCK引脚,禁止CS引脚控制,可用作IO */
+#define SPI_MODE_MASTER                     (0xA) /* 主模式,时钟=Fosc/(4*(SSPADD+1)) */
+/* spi_cpol spi时钟极性选择 */
+#define SPI_CPOL_0                          (0x0) /* 时钟低电平为空闲 */
+#define SPI_CPOL_1                          (0x1) /* 时钟高电平为空闲 */
+/* spi_cpha spi时钟相位选择 */
+#define SPI_CPHA_0                          (0x0) /* 时钟从空闲转到有效时发送(第一个跳变沿发送) */
+#define SPI_CPHA_1                          (0x1) /* 时钟从有效转到空闲时发送(第二个跳变沿发送) */
+    
+/* 类型定义-------------------------------------------------------------------*/
+typedef struct spi_config {
+    uint8_t mode : 4; /* SPI模式 @ref spi_mode */
+    uint8_t cpol : 2; /* 时钟极性 @ref spi_cpol */
+    uint8_t cpha : 2; /* 时钟相位 @ref spi_cpha */
+    uint8_t freqDiv; /* 时钟分频 2~255 仅在模式为SPI_MODE_MASTER时可用 */
+} spi_config_t;
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void spi_init(spi_config_t config);
+uint8_t spi_rw(uint8_t byte);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* spi.h */

+ 76 - 0
src/timer0.c

@@ -0,0 +1,76 @@
+/**
+  ******************************************************************************
+  * @file    timer0.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-12
+  * @brief   timer0驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-12    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "timer0.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  timer0初始化
+  * @note   定时周期sec = 1/(Fosc/4/预分频/(0xFF-初值))
+  * @param  value : timer0计数初值
+  * @retval None
+  */
+void timer0_init(uint8_t value)
+{
+    TMR0CS = 0; /* timer0时钟源选择位 0:内部时钟(Fosc/4) 1:T0CKI引脚上的电平跳变 */
+    TMR0SE = 0; /* timer0时钟源边沿选择位 0:上升沿递增  1:下降沿递增 */
+    PSA = 1; /* 预分频器分配位 0:预分频器分配给timer0 1:预分频器不分配给timer0 */
+    OPTION_REGbits.PS = 0; /* 预分频比 0:2 1:4 2:8 3:16 4:32 5:64 6:128 7:256 */
+    TIMER0_SET_INITIAL_VAL(value);
+    
+    timer0_update_it_cmd(0);
+}
+
+/**
+  * @brief  timer0取消初始化(恢复缺省)
+  * @param  None
+  * @retval None
+  */
+void timer0_de_init(void)
+{
+    TMR0CS = 1;
+    TMR0SE = 1;
+    PSA = 1;
+    OPTION_REGbits.PS = 1;
+    TMR0 = 0;
+    TMR0IF = 0;
+    TMR0IE = 0;
+}
+
+/**
+  * @brief  timer0溢出(更新)中断控制
+  * @param  state : 0禁止中断 1允许中断
+  * @retval None
+  */
+void timer0_update_it_cmd(uint8_t state)
+{
+    TMR0IF = 0; /* 清除timer0溢出位 0:未溢出 1:溢出 */
+    TMR0IE = state; /* timer0溢出中断允许位 0:禁止中断 1:允许中断 */
+}
+
+

+ 44 - 0
src/timer0.h

@@ -0,0 +1,44 @@
+/**
+  ******************************************************************************
+  * @file    timer0.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-12
+  * @brief   timer0驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __TIMER0_H
+#define __TIMER0_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+#define TIMER0_IT_FLAG                      TMR0IF /* timer0溢出中断标志 */
+
+#define TIMER0_SET_INITIAL_VAL(val)         (TMR0 = (val)) /* 设置timer0计数初值 */
+    
+/* 类型定义-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void timer0_init(uint8_t value);
+void timer0_de_init(void);
+void timer0_update_it_cmd(uint8_t state);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timer0.h */

+ 117 - 0
src/timer1.c

@@ -0,0 +1,117 @@
+/**
+  ******************************************************************************
+  * @file    timer1.c
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-17
+  * @brief   timer1驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Change Logs:
+  * Date          Author        Notes
+  * 2024-01-17    ashuai0110    完成基本内容
+  *
+  ******************************************************************************
+  */
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "timer1.h"
+
+/* 私有宏定义-----------------------------------------------------------------*/
+
+/* 私有类型定义---------------------------------------------------------------*/
+
+/* 私有变量-------------------------------------------------------------------*/
+
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 私有函数原型---------------------------------------------------------------*/
+
+/**
+  * @brief  timer1初始化
+  * @note   定时周期sec = 1/(Fosc/4/预分频/(0xFF-初值))
+  * @param  value : timer0计数初值
+  * @retval None
+  */
+void timer1_init(uint16_t value)
+{
+    T1CONbits.TMR1CS = 0; /* timer1时钟源选择位 0:Fosc/4  1:Fosc */
+    T1CONbits.T1CKPS = 0; /* 预分频比 0:1 1:2 2:4 3:8 */
+    
+    TIMER1_SET_INITIAL_VAL(value);
+    TMR1ON = 1;
+    timer1_update_it_cmd(1);
+}
+
+/**
+  * @brief  timer0取消初始化(恢复缺省)
+  * @param  None
+  * @retval None
+  */
+void timer1_de_init(void)
+{
+    T1CON = 0;
+    T1GCON = 0;
+    TMR1H = 0;
+    TMR1L = 0;
+    TMR1IF = 0;
+    TMR1IE = 0;
+}
+
+/**
+  * @brief  timer1溢出(更新)中断控制
+  * @param  state : 0禁止中断 1允许中断
+  * @retval None
+  */
+void timer1_update_it_cmd(uint8_t state)
+{
+    TMR1IF = 0; /* 清除timer1溢出位 0:未溢出 1:溢出 */
+    TMR1IE = state; /* timer1溢出中断允许位 0:禁止中断 1:允许中断 */
+}
+
+void timer1_ccpx_init(uint8_t ccpx, uint16_t value)
+{
+    switch(ccpx)
+    {
+        case 1:
+            CCP1CONbits.CCP1M = 0b1010;
+            CCPR1H = value >> 8;
+            CCPR1L = value & 0xFF;
+            break;
+        case 2:
+            CCP2CONbits.CCP2M = 0b1010;
+            CCPR2H = value >> 8;
+            CCPR2L = value & 0xFF;
+            break;
+        case 3:
+            CCP3CONbits.CCP3M = 0b1010;
+            CCPR3H = value >> 8;
+            CCPR3L = value & 0xFF;
+            break;
+    }
+    
+    timer1_ccpx_it_cmd(ccpx,1);
+}
+
+void timer1_ccpx_it_cmd(uint8_t ccpx, uint8_t state)
+{
+    switch(ccpx)
+    {
+        case 1:
+            CCP1IF = 0;
+            CCP1IE = state;
+            break;
+        case 2:
+            CCP2IF = 0;
+            CCP2IE = state;
+            break;
+        case 3:
+            CCP3IF = 0;
+            CCP3IE = state;
+            break;
+    }
+}
+
+

+ 66 - 0
src/timer1.h

@@ -0,0 +1,66 @@
+/**
+  ******************************************************************************
+  * @file    timer1.h
+  * @author  ashuai0110
+  * @version V1.0
+  * @date    2024-01-17
+  * @brief   timer1驱动,适用于PIC16(L)F1788_9
+  *
+  ******************************************************************************
+  * @attention
+  *
+  ******************************************************************************
+  */
+
+#ifndef __TIMER1_H
+#define __TIMER1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 包含头文件-----------------------------------------------------------------*/
+#include "common.h"
+
+/* 宏定义---------------------------------------------------------------------*/
+#define TIMER1_GET_IT_FLAG()                (TMR1IF) /* 获取timer1溢出中断标志 */
+#define TIMER1_CLR_IT_FLAG()                (TMR1IF = 0) /* 清除timer1溢出中断标志 */
+
+#define TIMER1_GET_GIT_FLAG()               (TMR1GIF) /* 获取timer1门控中断标志 */
+#define TIMER1_CLR_GIT_FLAG()               (TMR1GIF = 0) /* 清除timer1门控中断标志 */
+    
+#define TIMER1_SET_INITIAL_VAL(val)         (TMR1L = ((val) & 0xFF), TMR1H = ((val) >> 8)) /* 设置timer1计数初值 */
+    
+#define TIMER1_CMD(x)                       (TMR1ON = (x))
+    
+#define CCP1_GET_IT_FLAG()                  (CCP1IF)
+#define CCP1_CLR_IT_FLAG()                  (CCP1IF = 0)
+    
+#define CCP2_GET_IT_FLAG()                  (CCP2IF)
+#define CCP2_CLR_IT_FLAG()                  (CCP2IF = 0)
+
+#define CCP3_GET_IT_FLAG()                  (CCP3IF)
+#define CCP3_CLR_IT_FLAG()                  (CCP3IF = 0)
+    
+#define CCP1_SET_INITIAL_VAL(val)           (CCPR1L = ((val) & 0xFF), CCPR1H = ((val) >> 8))
+    
+#define CCP2_SET_INITIAL_VAL(val)           (CCPR2L = ((val) & 0xFF), CCPR2H = ((val) >> 8))
+    
+#define CCP3_SET_INITIAL_VAL(val)           (CCPR3L = ((val) & 0xFF), CCPR3H = ((val) >> 8))
+    
+/* 类型定义-------------------------------------------------------------------*/
+    
+/* 全局变量-------------------------------------------------------------------*/
+
+/* 函数原型-------------------------------------------------------------------*/
+void timer1_init(uint16_t value);
+void timer1_de_init(void);
+void timer1_update_it_cmd(uint8_t state);
+void timer1_ccpx_init(uint8_t ccpx, uint16_t value);
+void timer1_ccpx_it_cmd(uint8_t ccpx, uint8_t state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timer1.h */