From bfdf8f12135b116f20bca49cdc55800c606d4a22 Mon Sep 17 00:00:00 2001 From: IOsetting Date: Sat, 1 Jan 2022 17:43:23 +0800 Subject: [PATCH] feat: pca pwm demos --- demo/pca/pca_pwm_10bit_2ch.c | 71 +++++++++++++++++++++++++++++++++++ demo/pca/pca_pwm_8bit_2ch.c | 72 ++++++++++++++++++++++++++++++++++++ include/fw_pca.h | 56 +++++++++++++++++++++------- 3 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 demo/pca/pca_pwm_10bit_2ch.c create mode 100644 demo/pca/pca_pwm_8bit_2ch.c diff --git a/demo/pca/pca_pwm_10bit_2ch.c b/demo/pca/pca_pwm_10bit_2ch.c new file mode 100644 index 0000000..b719250 --- /dev/null +++ b/demo/pca/pca_pwm_10bit_2ch.c @@ -0,0 +1,71 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fw_hal.h" + +__BIT dir = SET; +uint16_t dc = 0; + +void main(void) +{ + SYS_SetClock(); + // UART1, baud 115200, baud source Timer1, 1T mode, no interrupt + UART1_ConfigMode1Dyn8bitUart(UART1_BaudSource_Timer1, HAL_State_ON, 115200); + + // Set GPIO pin mode + GPIO_P3_SetMode(GPIO_Pin_2|GPIO_Pin_3, GPIO_Mode_Output_PP); + + // Stop PCA/PWM + PCA_SetCounterState(HAL_State_OFF); + // Stop counter in idle mode + PCA_SetStopCounterInIdle(HAL_State_ON); + // Use SYSCLK as clock source + PCA_SetClockSource(PCA_ClockSource_SysClkDiv12); + // Turn off overflow interrupt + PCA_EnableCounterOverflowInterrupt(HAL_State_OFF); + + // Set PCA0 and PCA1 to PWM mode + PCA_PCA0_SetWorkMode(PCA_WorkMode_PWM_NonInterrupt); + PCA_PCA1_SetWorkMode(PCA_WorkMode_PWM_NonInterrupt); + // Set both to 8-bit PWM + PCA_PWM0_SetBitWidth(PCA_PWM_BitWidth_10); + PCA_PWM1_SetBitWidth(PCA_PWM_BitWidth_10); + // Set initial duty cycle + PCA_PCA0_SetCompareValue10bit(dc); + PCA_PCA1_SetCompareValue10bit(~dc & 0x3FF); + // Set output port for STC8G1K08A, PWM0:P32, PWM1:P33 + PCA_SetPort(PCA_AlterPort_G1K08A_P55_P32_P33_P54); + // Start PWM + PCA_SetCounterState(HAL_State_ON); + + while(1) + { + PCA_PCA0_ChangeCompareValue10bit(dc); + PCA_PCA1_ChangeCompareValue10bit(~dc & 0x3FF); + UART1_TxHex(dc >> 8); + UART1_TxHex(dc & 0xFF); + if (dir) + { + dc++; + if (dc == 0x03FF) dir = !dir; + } + else + { + dc--; + if (dc == 0) dir = !dir; + } + UART1_TxString("\r\n"); + SYS_Delay(10); + } +} \ No newline at end of file diff --git a/demo/pca/pca_pwm_8bit_2ch.c b/demo/pca/pca_pwm_8bit_2ch.c new file mode 100644 index 0000000..626866b --- /dev/null +++ b/demo/pca/pca_pwm_8bit_2ch.c @@ -0,0 +1,72 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fw_hal.h" + +__BIT dir = SET; +uint8_t dc = 0; + +void main(void) +{ + SYS_SetClock(); + // UART1, baud 115200, baud source Timer1, 1T mode, no interrupt + UART1_ConfigMode1Dyn8bitUart(UART1_BaudSource_Timer1, HAL_State_ON, 115200); + + // Set GPIO pin mode + GPIO_P3_SetMode(GPIO_Pin_2|GPIO_Pin_3, GPIO_Mode_Output_PP); + + // Stop PCA/PWM + PCA_SetCounterState(HAL_State_OFF); + // Stop counter in idle mode + PCA_SetStopCounterInIdle(HAL_State_ON); + // Use SYSCLK as clock source + PCA_SetClockSource(PCA_ClockSource_SysClk); + // Turn off overflow interrupt + PCA_EnableCounterOverflowInterrupt(HAL_State_OFF); + + // Set PCA0 and PCA1 to PWM mode + PCA_PCA0_SetWorkMode(PCA_WorkMode_PWM_NonInterrupt); + PCA_PCA1_SetWorkMode(PCA_WorkMode_PWM_NonInterrupt); + // Set both to 8-bit PWM + PCA_PWM0_SetBitWidth(PCA_PWM_BitWidth_8); + PCA_PWM1_SetBitWidth(PCA_PWM_BitWidth_8); + // Set initial duty cycle + PCA_PCA0_SetCompareValue(dc); + PCA_PCA1_SetCompareValue(~dc); + // Set output port for STC8G1K08A, PWM0:P32, PWM1:P33 + PCA_SetPort(PCA_AlterPort_G1K08A_P55_P32_P33_P54); + // Start PWM + PCA_SetCounterState(HAL_State_ON); + + while(1) + { + PCA_PCA0_ChangeCompareValue(dc); + PCA_PCA1_ChangeCompareValue(~dc); + UART1_TxHex(dc); + UART1_TxChar(' '); + UART1_TxHex(~dc); + if (dir) + { + dc++; + if (dc == 0xFF) dir = !dir; + } + else + { + dc--; + if (dc == 0) dir = !dir; + } + UART1_TxString("\r\n"); + SYS_Delay(10); + } +} \ No newline at end of file diff --git a/include/fw_pca.h b/include/fw_pca.h index 92c6b4c..1275f30 100644 --- a/include/fw_pca.h +++ b/include/fw_pca.h @@ -54,7 +54,7 @@ typedef enum typedef enum { - // ECI CCP0 CCP1 CCP2 + // ECI CCP0 CCP1 CCP2 PCA_AlterPort_P12_P11_P10_P37 = 0x00, PCA_AlterPort_P34_P35_P36_P37 = 0x01, PCA_AlterPort_P24_P25_P26_P27 = 0x10, @@ -62,7 +62,7 @@ typedef enum typedef enum { - // ECI CCP0 CCP1 CCP2 + // ECI CCP0 CCP1 CCP2 PCA_AlterPort_G1K08A_P55_P32_P33_P54 = 0x00, PCA_AlterPort_G1K08A_P55_P31_P33_P54 = 0x01, PCA_AlterPort_G1K08A_P31_P32_P33_P55 = 0x10, @@ -70,7 +70,7 @@ typedef enum typedef enum { - // ECI CCP0 CCP1 CCP2 + // ECI CCP0 CCP1 CCP2 PCA_AlterPort_G1K08T_P13_P11_P10_P37 = 0x00, PCA_AlterPort_G1K08T_P34_P35_P36_P37 = 0x01, PCA_AlterPort_G1K08T_P54_P13_P14_P15 = 0x10, @@ -87,30 +87,58 @@ typedef enum #define PCA_SetClockSource(__SOURCE___) (CMOD = CMOD & ~(0x07 << 1) | ((__SOURCE___) << 1)) #define PCA_EnableCounterOverflowInterrupt(__STATE__) SFR_ASSIGN(CMOD, 0, __STATE__) -#define PCA_PCA0_SetMode(__MODE__) (CCAPM0 = (__MODE__)) -#define PCA_PCA1_SetMode(__MODE__) (CCAPM1 = (__MODE__)) -#define PCA_PCA2_SetMode(__MODE__) (CCAPM2 = (__MODE__)) +#define PCA_PCA0_SetWorkMode(__MODE__) (CCAPM0 = (__MODE__)) +#define PCA_PCA1_SetWorkMode(__MODE__) (CCAPM1 = (__MODE__)) +#define PCA_PCA2_SetWorkMode(__MODE__) (CCAPM2 = (__MODE__)) #define PCA_PWM0_SetBitWidth(__BIT_WIDTH__) (PCA_PWM0 = PCA_PWM0 & ~(0x03 << 6) | ((__BIT_WIDTH__) << 6)) #define PCA_PWM1_SetBitWidth(__BIT_WIDTH__) (PCA_PWM1 = PCA_PWM1 & ~(0x03 << 6) | ((__BIT_WIDTH__) << 6)) #define PCA_PWM2_SetBitWidth(__BIT_WIDTH__) (PCA_PWM2 = PCA_PWM2 & ~(0x03 << 6) | ((__BIT_WIDTH__) << 6)) +/** + * Set initiale comparison value +*/ +#define PCA_PCA0_SetCompareValue(__VALUE__) do{CCAP0H = (__VALUE__); CCAP0L = (__VALUE__);}while(0) +#define PCA_PCA1_SetCompareValue(__VALUE__) do{CCAP1H = (__VALUE__); CCAP1L = (__VALUE__);}while(0) +#define PCA_PCA2_SetCompareValue(__VALUE__) do{CCAP2H = (__VALUE__); CCAP2L = (__VALUE__);}while(0) +/** + * Change comparison value when running +*/ +#define PCA_PCA0_ChangeCompareValue(__VALUE__) (CCAP0H = (__VALUE__)) +#define PCA_PCA1_ChangeCompareValue(__VALUE__) (CCAP1H = (__VALUE__)) +#define PCA_PCA2_ChangeCompareValue(__VALUE__) (CCAP2H = (__VALUE__)) -// TODO: set high 8-bit should be enough -#define PCA_PCA0_SetCompareValue(__VALUE__) do{CCAP0H = (__VALUE__); CCAP0L = (__VALUE__);}while(0) -#define PCA_PCA1_SetCompareValue(__VALUE__) do{CCAP1H = (__VALUE__); CCAP1L = (__VALUE__);}while(0) -#define PCA_PCA2_SetCompareValue(__VALUE__) do{CCAP2H = (__VALUE__); CCAP2L = (__VALUE__);}while(0) -// TODO: set high 8-bit should be enough +/** + * Set initiale comparison value +*/ #define PCA_PCA0_SetCompareValue10bit(__VALUE__) do{ \ - CCAP0H = ((__VALUE__) & 0xFF); CCAP0L = ((__VALUE__) & 0xFF); \ PCA_PWM0 = PCA_PWM0 & ~(0x0F << 2) | (((__VALUE__) >> 4) & 0x30) | (((__VALUE__) >> 6) & 0x0C); \ + CCAP0H = ((__VALUE__) & 0xFF); CCAP0L = ((__VALUE__) & 0xFF); \ }while(0) #define PCA_PCA1_SetCompareValue10bit(__VALUE__) do{ \ - CCAP1H = ((__VALUE__) & 0xFF); CCAP1L = ((__VALUE__) & 0xFF); \ PCA_PWM1 = PCA_PWM1 & ~(0x0F << 2) | (((__VALUE__) >> 4) & 0x30) | (((__VALUE__) >> 6) & 0x0C); \ + CCAP1H = ((__VALUE__) & 0xFF); CCAP1L = ((__VALUE__) & 0xFF); \ }while(0) #define PCA_PCA2_SetCompareValue10bit(__VALUE__) do{ \ - CCAP2H = ((__VALUE__) & 0xFF); CCAP2L = ((__VALUE__) & 0xFF); \ PCA_PWM2 = PCA_PWM2 & ~(0x0F << 2) | (((__VALUE__) >> 4) & 0x30) | (((__VALUE__) >> 6) & 0x0C); \ + CCAP2H = ((__VALUE__) & 0xFF); CCAP2L = ((__VALUE__) & 0xFF); \ + }while(0) + +/** + * Change comparison value in running mode + * Note: set high 2bit first, then low 8bit, the hardware will make sure new 10bit be loaded as a whole number. + * If you write low bits first, it will introduce glitchnoise. +*/ +#define PCA_PCA0_ChangeCompareValue10bit(__VALUE__) do{ \ + PCA_PWM0 = PCA_PWM0 & ~(0x03 << 4) | (((__VALUE__) >> 4) & 0x30); \ + CCAP0H = ((__VALUE__) & 0xFF); \ + }while(0) +#define PCA_PCA1_ChangeCompareValue10bit(__VALUE__) do{ \ + PCA_PWM1 = PCA_PWM1 & ~(0x03 << 4) | (((__VALUE__) >> 4) & 0x30); \ + CCAP1H = ((__VALUE__) & 0xFF); \ + }while(0) +#define PCA_PCA2_ChangeCompareValue10bit(__VALUE__) do{ \ + PCA_PWM2 = PCA_PWM2 & ~(0x03 << 4) | (((__VALUE__) >> 4) & 0x30); \ + CCAP2H = ((__VALUE__) & 0xFF); \ }while(0) /**