- /***********************************************************************************************************************
- * [url=home.php?mod=space&uid=247401]@brief[/url] : D1->32000000Hz / 32000 = 1000Hz, 1ms D12->32000000Hz / 26666 = 100Hz, 10ms
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void TimeSliceInitTIM(void)
- {
- TIM0_DeInit();
- TIM0_TimeBaseInit(TIM0_PRESSEL_FSYS_D1, TIM0_MODE_TIMER);
- TIM0_WorkModeConfig(TIM0_WORK_MODE1, (65535 - 32000), 0);
- TIM0_ITConfig(ENABLE, LOW);
- TIM0_Cmd(ENABLE);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void TIM0_IRQHandler(void) interrupt 1
- {
- TIM0_Mode1SetReloadCounter(65535 - 32000);
- TIM0_Tick++;
- TimeSliceRunning(TIM0_Tick);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void TimeSliceRunning(uint32_t Tick)
- {
- TimeSlice_NodeTypeDef *Node = Head;
- while (NULL != Node)
- {
- if (0 == (Tick % Node->Period))
- {
- Node->RunFlag = 1;
- }
- Node = Node->Next;
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void TimeSlicePolling(void)
- {
- TimeSlice_NodeTypeDef *Node = Head;
- while (NULL != Node)
- {
- if (1 == Node->RunFlag)
- {
- Node->RunFlag = 0;
- Node->Handler();
- }
- Node = Node->Next;
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void main(void)
- {
- BSP_Init();
- TimeSliceInitTIM();
- enableInterrupts();
- while (1)
- {
- TimeSlicePolling();
- }
- }
任务的管理主要是创建,首先是定义一个任务,它有运行的间隔时间、可运行标志位、任务具体调用的功能函数、以及下一任务节点指针;通过链表的形式将各个节点的任务串连起来管理;其中使用到了malloc和free这两个动态内存分配和释放的函数,这个跟我们在32位MCU使用上还是有些区别的,主是需要定义一个内存池,对内存池进行初始化后才可以正常的运行malloc这些函数……具体的实现代码如下所示:
- /* Exported types *****************************************************************************************************/
- typedef void (* Function)(void);
- /* Exported types *****************************************************************************************************/
- typedef struct _Node_Struct
- {
- uint32_t Period;
- uint8_t RunFlag;
- Function Handler;
- struct _Node_Struct *Next;
- } TimeSlice_NodeTypeDef;
- /* Private variables **************************************************************************************************/
- static uint8_t xdata mempool[1024];
- TimeSlice_NodeTypeDef *Head = NULL;
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void TimeSliceStartup(Function Handler, uint32_t Period)
- {
- TimeSlice_NodeTypeDef *Node = Head;
- if (NULL == Head)
- {
- memset(mempool, 0x00, sizeof(mempool));
- init_mempool(mempool, sizeof(mempool));
- Head = (TimeSlice_NodeTypeDef *)malloc(sizeof(TimeSlice_NodeTypeDef));
- if (NULL == Head)
- {
- free(Head);
- }
- else
- {
- Head->Period = Period;
- Head->RunFlag = 0;
- Head->Handler = Handler;
- Head->Next = NULL;
- }
- }
- else
- {
- while (NULL != Node->Next)
- {
- if (Node->Handler == Handler)
- {
- Node->Period = Period;
- return;
- }
- else
- {
- Node = Node->Next;
- }
- }
- Node->Next = (TimeSlice_NodeTypeDef *)malloc(sizeof(TimeSlice_NodeTypeDef));
- if (NULL != Node->Next)
- {
- Node = Node->Next;
- Node->Period = Period;
- Node->RunFlag = 0;
- Node->Handler = Handler;
- Node->Next = NULL;
- }
- else
- {
- free(Node->Next);
- }
- }
- }
2、GPIO输出控制LED、GPIO输入检测KEY输入状态
GPIO是作为MCU的一个最基础的功能,通过新定义提供的低层库函数实现了LED亮灭的控制、通过状态机的方式实现了按键的检测和功能处理,具体代码如下所示:
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void LED_Init(void)
- {
- GPIO_Init(GPIO4, GPIO_PIN_6, GPIO_MODE_OUT_PP); /* L1->P46 */
- GPIO_Init(GPIO4, GPIO_PIN_7, GPIO_MODE_OUT_PP); /* L2->P47 */
- GPIO_WriteLow(GPIO4, GPIO_PIN_6);
- GPIO_WriteLow(GPIO4, GPIO_PIN_7);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void KEY_StateHandler(uint8_t Index, uint8_t *State, uint8_t *Count, uint8_t InputLevel, uint8_t ActiveLevel)
- {
- if (0 == *State)
- {
- if (InputLevel == ActiveLevel)
- {
- *Count += 1;
- if (*Count >= 5)
- {
- *Count = 0;
- *State = 1;
- KEY_EventHandler(Index, 1);
- }
- }
- else
- {
- *Count = 0;
- }
- }
- else
- {
- if (InputLevel != ActiveLevel)
- {
- *Count += 1;
- if (*Count >= 5)
- {
- *Count = 0;
- *State = 0;
- KEY_EventHandler(Index, 0);
- }
- }
- else
- {
- *Count = 0;
- }
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void KEY_Scan(void)
- {
- static uint8_t State[2] =
- {
- 0, 0
- };
- static uint8_t Count[2] =
- {
- 0, 0
- };
- KEY_StateHandler(0, &State[0], &Count[0], GPIO_ReadPin(GPIO3, GPIO_PIN_6), RESET);
- KEY_StateHandler(1, &State[1], &Count[1], GPIO_ReadPin(GPIO5, GPIO_PIN_4), RESET);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void KEY_Init(void)
- {
- GPIO_Init(GPIO3, GPIO_PIN_6, GPIO_MODE_IN_PU); /* K1->P36 */
- GPIO_Init(GPIO5, GPIO_PIN_4, GPIO_MODE_IN_PU); /* K2->P54 */
- TimeSliceStartup(KEY_Scan, 10);
- }
3、3路PWM输出控制RGB灯,根据人体视觉感观,控制RGB亮度调节、颜色切换
RGB的亮度调节是通过修改PWM的占空比实现的,颜色的切换是通过开关不同的PWM通道实现的,在亮度调节上我们使用了LOG参数的形式进行计算后调节,使人体视觉感观更自然,调节更舒适,具体代码如下所示:
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- double RGB_GetLOG(double Level, double MAX)
- {
- return pow(10, Level * log10(999) / MAX);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void RGB_Scan(void)
- {
- static uint8_t Index = 0;
- static uint8_t State = 0, Level = 0, MAX = 100;
- switch (Index)
- {
- case 0:
- PWM_IndependentModeConfig(PWM01, RGB_GetLOG(Level, MAX));
- PWM_IndependentModeConfig(PWM00, 0);
- PWM_IndependentModeConfig(PWM03, 0);
- break;
- case 1:
- PWM_IndependentModeConfig(PWM01, 0);
- PWM_IndependentModeConfig(PWM00, RGB_GetLOG(Level, MAX));
- PWM_IndependentModeConfig(PWM03, 0);
- break;
- case 2:
- PWM_IndependentModeConfig(PWM01, 0);
- PWM_IndependentModeConfig(PWM00, 0);
- PWM_IndependentModeConfig(PWM03, RGB_GetLOG(Level, MAX));
- break;
- default:
- break;
- }
- if (State == 0)
- {
- if (Level >= MAX)
- {
- Level = MAX;
- State = 1;
- }
- else
- {
- Level++;
- }
- }
- else
- {
- if (Level <= 1)
- {
- Level = 1;
- State = 0;
- Index = (Index + 1) % 3;
- }
- else
- {
- Level--;
- }
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void RGB_Init(void)
- {
- PWM_Init(PWM0_PRESSEL_FHRC_D1, 255);
- PWM_IndependentModeConfigEX(PWM00, 0, PWM_OUTPUTSTATE_ENABLE);
- PWM_IndependentModeConfigEX(PWM01, 0, PWM_OUTPUTSTATE_ENABLE);
- PWM_IndependentModeConfigEX(PWM03, 0, PWM_OUTPUTSTATE_ENABLE);
- // PWM_Aligned_Mode_Select(PWM0_Edge_Aligned_Mode);
- // PWM_FaultDetectionConfigEX(PWM0_Type, DISABLE);
- // PWM_FaultDetectionModeConfigEX(PWM0_Type, PWM0_Immediate_Mode, PWM0_FaultDetectionVoltage_Low, PWM0_WaveFilteringTime_0us);
- PWM_CmdEX(PWM0_Type, ENABLE);
- TimeSliceStartup(RGB_Scan, 20);
- }
这边就是对PWM的PWM_FaultDetectionConfigEX、PWM_FaultDetectionModeConfigEX这两个函数的应用功能不是太了解……
4、1路PWM控制蜂鸣器
对于蜂鸣器的控制我们可以使用将PWM使能或禁止的方式来控制,也可以通过修改PWM占空比的方式来控制;对于这两种方式,都做过尝试:使用将PWM使能或禁止的方式控制便捷,语句调度简单,但在下载MCU程序时,PWM存在触发蜂鸣器的嗒嗒声;而通过修改PWM占空比的方式,在下载程序时蜂鸣器不会误响,但在控制上需要注意,不能以极快的速度去切换PWM的占空比,这样有可能会导致程序卡死或者是MCU卡死(具体哪个卡了,还没分析),参考程序如下:
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void BUZZER_Init(void)
- {
- #if 0
- uint16_t Frequency = 32000000 / BUZZER_PWM_FREQ;
- uint16_t Duty = 32000000 / BUZZER_PWM_FREQ * BUZZER_PWM_DUTY / 100;
- PWM_DeInit();
- PWM_Init(PWM4_PRESSEL_FHRC_D1, Frequency);
- PWM_IndependentModeConfigEX(PWM40, Duty, PWM_OUTPUTSTATE_ENABLE);
- PWM_CmdEX(PWM4_Type, DISABLE);
- #else
- PWM_DeInit();
- PWM_Init(PWM4_PRESSEL_FHRC_D1, 32000000 / BUZZER_PWM_FREQ);
- PWM_IndependentModeConfigEX(PWM40, 0, PWM_OUTPUTSTATE_ENABLE);
- PWM_CmdEX(PWM4_Type, ENABLE);
- #endif
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void BUZZER_Enable(uint8_t State)
- {
- #if 0
- if (ENABLE == State)
- {
- PWM_CmdEX(PWM4_Type, ENABLE);
- }
- else
- {
- PWM_CmdEX(PWM4_Type, DISABLE);
- }
- #else
- if (ENABLE == State)
- {
- PWM_IndependentModeConfig(PWM40, 32000000 / BUZZER_PWM_FREQ * BUZZER_PWM_DUTY / 100);
- }
- else
- {
- PWM_IndependentModeConfig(PWM40, 0);
- }
- #endif
- }
5、通过芯片的LCD/LED外设功能驱动显示4位8段数码管
新定义的这款MCU不仅支持触摸功能,还带有LCD/LED段码显示功能,每一个段和位在MCU都对应一个显示内存,根据硬件设计在配置好相应的显示参数后,可以直接操作内存显示我们想要的内容,参考代码如下:
- /* Private typedef ****************************************************************************************************/
- typedef struct
- {
- char ch;
- uint8_t Data;
- } LED_CodeTypeDef;
- /* Private define *****************************************************************************************************/
- /* Private macro ******************************************************************************************************/
- /* Private variables **************************************************************************************************/
- code LED_CodeTypeDef LED_CODE_TAB[38] =
- {
- { ' ', 0x00 },
- { '0', 0x3F },
- { '1', 0x06 },
- { '2', 0x5B },
- { '3', 0x4F },
- { '4', 0x66 },
- { '5', 0x6D },
- { '6', 0x7D },
- { '7', 0x07 },
- { '8', 0x7F },
- { '9', 0x6F },
- { 'A', 0x77 },
- { 'b', 0x7C },
- { 'c', 0x58 },
- { 'C', 0x39 },
- { 'd', 0x5E },
- { 'E', 0x79 },
- { 'F', 0x71 },
- { 'g', 0x6F },
- { 'H', 0x76 },
- { 'h', 0x74 },
- { 'i', 0x04 },
- { 'I', 0x30 },
- { 'J', 0x1E },
- { 'l', 0x30 },
- { 'L', 0x38 },
- { 'n', 0x54 },
- { 'o', 0x5C },
- { 'O', 0x3F },
- { 'P', 0x73 },
- { 'q', 0x67 },
- { 'r', 0x50 },
- { 'S', 0x6D },
- { 't', 0x78 },
- { 'u', 0x1C },
- { 'U', 0x3E },
- { 'y', 0x6E },
- { '-', 0x40 },
- };
- uint8_t LED_DisplayMode = 0;
- /* Private functions **************************************************************************************************/
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void LED_DisplayNumber(uint8_t Index, uint8_t Data)
- {
- DDIC_Control_COM_TypeDef DDIC_COMn[4] =
- {
- DDIC_COM3, DDIC_COM2, DDIC_COM1, DDIC_COM0
- };
- DDIC_Control(DDIC_SEG4, DDIC_COMn[Index], (Data >> 0x00) & 0x01);
- DDIC_Control(DDIC_SEG16, DDIC_COMn[Index], (Data >> 0x01) & 0x01);
- DDIC_Control(DDIC_SEG18, DDIC_COMn[Index], (Data >> 0x02) & 0x01);
- DDIC_Control(DDIC_SEG20, DDIC_COMn[Index], (Data >> 0x03) & 0x01);
- DDIC_Control(DDIC_SEG23, DDIC_COMn[Index], (Data >> 0x04) & 0x01);
- DDIC_Control(DDIC_SEG6, DDIC_COMn[Index], (Data >> 0x05) & 0x01);
- DDIC_Control(DDIC_SEG17, DDIC_COMn[Index], (Data >> 0x06) & 0x01);
- DDIC_Control(DDIC_SEG19, DDIC_COMn[Index], (Data >> 0x07) & 0x01);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void LED_DisplayString(char *str)
- {
- uint8_t i = 0, Index = 0;
- while ((*str != '\0') && (Index < 4))
- {
- for (i = 0; i < 38; i++)
- {
- if (*str == LED_CODE_TAB[i].ch)
- {
- LED_DisplayNumber(Index, LED_CODE_TAB[i].Data);
- }
- }
- str++;
- Index++;
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void LED_Scan(void)
- {
- static uint16_t Count = 0;
- char str[10];
- if (0 == LED_DisplayMode)
- {
- memset(str, 0, sizeof(str));
- sprintf(str, "%04d", Count);
- LED_DisplayString(str);
- Count = (Count + 1) % 10000;
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void LED_Init(void)
- {
- DDIC_DMOD_Selcet(DMOD_LED);
- DDIC_Init(DDIC_DUTYCYCLE_D4,
- DDIC_PIN_X0 | DDIC_PIN_X3,
- DDIC_PIN_X0 | DDIC_PIN_X2,
- DDIC_PIN_X4 | DDIC_PIN_X5 | DDIC_PIN_X6 | DDIC_PIN_X7,
- DDIC_PIN_X0 | DDIC_PIN_X1 | DDIC_PIN_X2 | DDIC_PIN_X3);
- DDIC_OutputPinOfDutycycleD4(SEG4_27COM0_3);
- DDIC_Cmd(ENABLE);
- TimeSliceStartup(LED_Scan, 100);
- }
6、通过板载的可调节电阻实现ADC检测与显示、通过2个可调节电阻实现比较器的功能
板载两个可调电阻,一个可调电阻是用于ADC采样调节的,另外一个电阻是用来调节比较器的外部比较电压的;通过这两个可调电阻,我们既可以实现ADC的功能,也可以实现比较器的功能,参考代码如下:
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ADC_Configure(void)
- {
- ADC_Init(ADC_PRESSEL_3CLOCK, ADC_Cycle_Null);
- ADC_EAINConfig(ADC_EAIN_7, ENABLE);
- ADC_EAINConfig(ADC_EAIN_15, ENABLE);
- ADC_Cmd(ENABLE);
- TimeSliceStartup(ADC_Scan, 200);
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- uint16_t ADC_GetADCValue(ADC_Channel_TypeDef Channel)
- {
- uint16_t Value = 0;
- ADC_ChannelConfig(Channel, ENABLE);
- ADC_StartConversion();
- while (RESET == ADC_GetFlagStatus())
- {
- _nop_();
- }
- return (ADC_GetConversionValue());
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void CMP_Scan(void)
- {
- static uint8_t State = 0;
- if (3 == LED_DisplayMode)
- {
- if (CMPCON & (ACMP_FLAG_CMPSTA)) /* CMP3 > CMPR */
- {
- if (1 != State)
- {
- State = 1;
- BUZZER_Enable(ENABLE);
- }
- }
- else /* CMP3 < CMPR */
- {
- if (0 != State)
- {
- State = 0;
- BUZZER_Enable(DISABLE);
- }
- }
- LED_DisplayString("----");
- }
- }
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void CMP_Init(void)
- {
- ACMP_Init(ACMP_VREF_8D16VDD, ACMP_VREF_EXTERNAL);
- ACMP_Cmd(ENABLE);
- TimeSliceStartup(CMP_Scan, 20);
- }
7、NTC实时温度检测与显示
NTC也是通过MCU的ADC功能来实现的,首先采样NTC的ADC数据,然后根据NTC的特性表对应的温度进行查表换算,最后通过LED数码管显示出来,参考代码如下:
- /* Private variables **************************************************************************************************/
- code uint16_t NTC_ADC_MapTable[100] =
- {
- 248 , 262 , 277 , 293 , 310 , 327 , 345 , 364 , 384 , 404 ,
- 425 , 447 , 470 , 494 , 518 , 543 , 570 , 597 , 624 , 653 ,
- 683 , 713 , 744 , 776 , 809 , 842 , 877 , 912 , 948 , 984 ,
- 1022, 1060, 1098, 1137, 1177, 1217, 1258, 1299, 1341, 1383,
- 1425, 1468, 1511, 1554, 1598, 1641, 1685, 1729, 1772, 1816,
- 1860, 1903, 1946, 1990, 2033, 2075, 2117, 2159, 2201, 2243,
- 2283, 2324, 2364, 2403, 2442, 2481, 2519, 2556, 2593, 2629,
- 2664, 2699, 2734, 2767, 2800, 2833, 2864, 2895, 2926, 2956,
- 2985, 3013, 3041, 3069, 3095, 3121, 3147, 3172, 3195, 3219,
- 3242, 3265, 3286, 3308, 3328, 3348, 3368, 3388, 3406, 3424,
- };
- /***********************************************************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *********************************************************************************************************************/
- void ADC_Scan(void)
- {
- char str[10];
- uint16_t i = 0;
- uint16_t Value;
- if (1 == LED_DisplayMode) /* CMP3 */
- {
- Value = ADC_GetADCValue(ADC_CHANNEL_15);
- memset(str, 0, sizeof(str));
- sprintf(str, "%04d", Value);
- LED_DisplayString(str);
- }
- if (2 == LED_DisplayMode) /* NTC */
- {
- Value = ADC_GetADCValue(ADC_CHANNEL_7);
- for(i = 0; i < 99; i++)
- {
- if((Value >= NTC_ADC_MapTable[i]) && (Value < NTC_ADC_MapTable[i + 1]))
- {
- break;
- }
- }
- memset(str, 0, sizeof(str));
- if(i < 15)
- {
- sprintf(str, "-%02dC", 15 - i);
- }
- else
- {
- sprintf(str, "%03dCC", i - 15);
- }
- LED_DisplayString(str);
- }
- }
最后直接贴上完整的工程源代码:
Project_NBK-RD8x3x_NBK-EBS002.zip
(203.31 KB, 下载次数: 12)
最终效果演示视频: