分享一套基于BS818A的八位电容触摸按键方案
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
成品pcb正面和背面:
元件清单:
STM8L15x-16x-05x-AL31-L_StdPeriph_Lib 原文件夹名称/库名称。
1.触发关闭的动作从中断it文件中拿出。
某些情况下,可能出现设定左右中断后halt过程中。突然进入中断,关闭中断,导致再也无法唤醒。
2.代码里面放一个计数器,计算唤醒的次数。
3.ADC 的while(1)等待需要做一个超时限制。
4.整机需要RTC唤醒,或者看门狗么?
5.需要减少唤醒功耗。
6.
///////////////////
1.2016-06-18增加没有传感接入情况下的Err显示。
2.
/////////
1.增加开机后的debug显示。
2.关闭初始化后的debug。
3.增加一个次数的变量。增加一个唤醒次数的变量。
4.增加检测detect引脚,触发debug输出的代码。
5.修改err显示值的设定范围。----------------------------
6.修改电池电压的获取时间。----------------------------
7.关闭屏幕的时候,按照正确的流程来。将多余的电留在屏幕电容里面上,估计可以减少对启动电流的需求。
8.
///////////////////////////
1.修改detect pin输出的debug信息。=========
2.增加独立watchdog。=========
3.显示时间增加到5秒==========
4.修改option 代码为 00 00 00 03 00 00 00 00 ,iwatchdog 由硬件启动,halt后停止,关闭代码读取。===========
5.增加reset次数记录和显示。
PCB空板使用说明
1.焊接电池座时,注意焊盘正负极。
2.根据自己的需要,在按键上覆盖按键面板材料。
3.J1跳线用于测试整机功耗。
4.J11跳线用于测试芯片的工作模式(串行,并行)
5.J13跳线用于测试芯片的低功耗模式(会影响按键扫描速度)
6.整个板子可以根据需要,从中间切开,分成单独的芯片模块和MCU模块。以便使用其他方案驱动。
7.J12为STM8L的SWIM接口。
8.在粘接压克力等面板到PCB上时,建议使用3M的468MP无基材胶。
单片机源程序如下:
- /* Includes ------------------------------------------------------------------*/
- #include "stm8l15x.h"
- #include "main.h"
- /** @addtogroup STM8L15x_StdPeriph_Template
- * @{
- */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- void DEBUGBOARD_Init(void);
- void GPIO_LowPower_Config(void);
- void IWDG_Config(void);
- /* Private functions ---------------------------------------------------------*/
- #define NSS_H GPIO_SetBits(GPIOA, GPIO_Pin_2)
- #define NSS_L GPIO_ResetBits(GPIOA, GPIO_Pin_2)
- #define DATA_H GPIO_SetBits(GPIOD, GPIO_Pin_0)
- #define DATA_L GPIO_ResetBits(GPIOD, GPIO_Pin_0)
- #define SCK_H GPIO_SetBits(GPIOA, GPIO_Pin_3)
- #define SCK_L GPIO_ResetBits(GPIOA, GPIO_Pin_3)
- void delay_us(volatile uint32_t times)
- {
- while(times--);
- }
- void GPIO_LowPower_Config(void)
- {
- #if 1////all low out
- GPIO_Init(GPIOA, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Fast);//SWIM
- GPIO_Init(GPIOA, GPIO_Pin_1, GPIO_Mode_Out_PP_Low_Fast);///NRST
- GPIO_Init(GPIOA, GPIO_Pin_2, GPIO_Mode_In_FL_No_IT);//bin1
- GPIO_Init(GPIOA, GPIO_Pin_3, GPIO_Mode_In_FL_No_IT);//bin0
- GPIO_Init(GPIOB, GPIO_Pin_0, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_1, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_2, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_3, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_4, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_Out_PP_High_Fast);///
- GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Fast);////SDA
- GPIO_Init(GPIOC, GPIO_Pin_1, GPIO_Mode_Out_PP_Low_Fast);////SCL
- GPIO_Init(GPIOC, GPIO_Pin_4, GPIO_Mode_Out_PP_Low_Fast);////
- GPIO_Init(GPIOC, GPIO_Pin_5, GPIO_Mode_In_FL_No_IT);///bin3
- GPIO_Init(GPIOC, GPIO_Pin_6, GPIO_Mode_In_FL_No_IT);///bin2
- GPIO_Init(GPIOD, GPIO_Pin_0, GPIO_Mode_In_FL_No_IT);///debug data
- #endif
- }
- void testpin(uint8_t high_low)
- {
- if(high_low == 1)
- GPIO_SetBits(GPIOC,GPIO_Pin_6);
- else
- GPIO_ResetBits(GPIOC,GPIO_Pin_6);
- }
- void Init(void)
- {
- //IWDG_Config();
- /*High speed internal clock prescaler: 1*/
- CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
- //GPIO_Config();
- GPIO_LowPower_Config();
- //ADC_Periph_Init();///2017-01-04
-
- #if 1//def DEBUG
- ///DEBUGBOARD_Init();///move in GPIO_LowPower_Config();
- #endif
- }
- void Power_Ctrl(uint8_t onoff)
- {
- if(onoff == 1)///////更换了电阻为上拉。(更加省电)2016-05-11/////带mos 管,1
- {
- GPIO_ResetBits(GPIOB, GPIO_Pin_7);///通电
- }
- else
- {
- GPIO_SetBits(GPIOB, GPIO_Pin_7);///断电
- }
- }
- void uart_put(uint8_t data)/////new 2016-07-19///////因为中断问题,80->100
- {
- uint8_t i;
- NSS_L;
- SCK_L;
- if((data&0x80)!=0)/////第一个bit data
- DATA_H;
- else
- DATA_L;
- delay_us(10);
- SCK_H;
- for(i=1;i<8;i++)
- {
- delay_us(10);
- SCK_L;
- NSS_H;/////////////////完成识别后才拉高。
-
- if(((data<<i)&0x80)!=0)
- DATA_H;
- else
- DATA_L;
- delay_us(10);
- SCK_H;
- }
- delay_us(10);//////每个byte的间隙。
- }
- void DEBUGBOARD_Init(void)
- {
- /* Enable AHB clock to the GPIO domain. */
- //LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
- GPIO_Init(GPIOA, GPIO_Pin_2, GPIO_Mode_Out_PP_Low_Fast);//ce
- GPIO_Init(GPIOA, GPIO_Pin_3, GPIO_Mode_Out_PP_Low_Fast);//clk
- GPIO_Init(GPIOD, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Fast);//data
- }
- void RTC_Config(uint16_t time)//////////////两个RTC 会冲突。在需要调用的时候通过改变CLK源实现重启。2017-01-06
- {
- CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
- #if 0//def USE_LSE
- CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
- #else
- CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);///////内置晶振38K////////2375Hz
- #endif
- Calendar_Init();//////LSI 38k set to 1Hz spre
- /* Configures the RTC wakeup timer_step = RTCCLK/16 = LSE/16 = 488.28125 us */
- ///////ck_spre frequency = ck_apre frequency/(PREDIV_S+1)
- ///////ck_apre frequency = fRTCCLK frequency/ (PREDIV_A+1)
- ///////ck_spre frequency = (fRTCCLK frequency/ (PREDIV_A+1))/(PREDIV_S+1)
- ///////RTCCLK frequency = CLK_RTCCLKSource_LSI/CLK_RTCCLKDiv_1
- ///////ck_spre frequency = (38000/(0x7f+1))/(0x00ff+1) == 1s
- RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);////RTC_WakeUpClock_RTCCLK_Div16////---2375/16 = 148.43Hz == 0.0067368s///////////设置为1秒
-
- //RTC_BypassShadowCmd(DISABLE);/////////////////////move here 2016-05-29
- /* Enable wake up unit Interrupt */
- RTC_ITConfig(RTC_IT_WUT, ENABLE); //开启中断
-
- RTC_SetWakeUpCounter(time); //设置RTC Weakup计算器初值
-
- RTC_WakeUpCmd(ENABLE); //使能自动唤醒
- }
- void RTC_Config_old(void)
- {
- CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
- #ifdef USE_LSE
- CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
- #else
- CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);
- #endif
- /* Configures the RTC wakeup timer_step = RTCCLK/16 = LSE/16 = 488.28125 us */
- RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
- Calendar_Init();
- RTC_BypassShadowCmd(DISABLE);/////////////////////move here 2016-05-29
- /* Enable wake up unit Interrupt */
- RTC_ITConfig(RTC_IT_WUT, ENABLE);
-
- }
- uint8_t WakeUpModeParser(uint8_t wakeupsource,uint8_t timeout_func,uint8_t up_func,uint8_t down_func)
- {
- uint8_t sys_mod = SYS_STANDBY_MODE;
- if(wakeupsource == 1)///up
- {
- sys_mod = up_func;
- }
- else if(wakeupsource == 2)///down
- {
- sys_mod = down_func;
- }
- else if(wakeupsource == 3)////RTC wake up
- {
- sys_mod = timeout_func;
- #ifdef DEBUG
- printf_string("RTC wake\n");
- #endif
- }
- else
- {
- sys_mod = SYS_STANDBY_MODE;
- }
- return sys_mod;
-
- }
- void RTC_SetSleepTimer(uint8_t sleeptype,uint16_t counter)
- {
- if(counter == DISABLE)
- {
- RTC_WakeUpCmd(DISABLE);
- CLK_PeripheralClockConfig(CLK_Peripheral_RTC, DISABLE);
- }
- else
- {
- /////////定时器打开。///////1秒后唤醒RTC_Config();
- /* RTC wake-up event every 500 ms (timer_step x (1023 + 1) )*/
- CLK_PeripheralClockConfig(CLK_Peripheral_RTC,ENABLE);/////////temp 是不是可以移动到初始化的地方?2017-01-06
- if(sleeptype == TYPE_SHORTTIME)
- {
- RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
- RTC_SetWakeUpCounter((counter<<1));//RTC wakeup timer_step = RTCCLK/16 = LSE/16 = 488.28125 us */////2048->1000ms //////~~= y=2X
- }
- else if(sleeptype == TYPE_LONGTIME)
- {
- RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);////RTC_WakeUpClock_RTCCLK_Div16////---2375/16 = 148.43Hz == 0.0067368s///////////设置为1秒
- RTC_SetWakeUpCounter(counter);
- }
- RTC_WakeUpCmd(ENABLE);
- }
-
- }
- volatile uint32_t g_timer_count = 0;
- void TIMER_Configuration(void)
- {
- TIM4_DeInit();
- /* Enable TIM4 Clock */
- CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
- /* Time base configuration */
- TIM4_TimeBaseInit(TIM4_Prescaler_16384, 0xf0 );
- /* Enable TIM4 IT UPDATE */
- TIM4_ITConfig(TIM4_IT_Update, ENABLE);
- /* Clear the Flag */
- TIM4_ClearFlag(TIM4_FLAG_Update);
- /* Enable TIM4 */
- TIM4_Cmd(ENABLE);
- }
- RTC_InitTypeDef RTC_InitStr;
- /**
- * @brief Calendar Configuration.
- * @param None
- * @retval None
- */
- void Calendar_Init(void)
- {
- RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;
- RTC_InitStr.RTC_AsynchPrediv = 0x7c;
- RTC_InitStr.RTC_SynchPrediv = 0x012F;
- RTC_Init(&RTC_InitStr);
- }
- ///////////////////////////////////////////////////////////////
- #define RELOAD_VALUE 254
- /**
- * @brief Configures the IWDG to generate a Reset if it is not refreshed at the
- * correct time.
- * @param None
- * @retval None
- */
- void IWDG_Config(void)
- {
- /* Enable IWDG (the LSI oscillator will be enabled by hardware) */
- IWDG_Enable();
-
- /* IWDG timeout equal to 214 ms (the timeout may varies due to LSI frequency
- dispersion) */
- /* Enable write access to IWDG_PR and IWDG_RLR registers */
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
-
- /* IWDG configuration: IWDG is clocked by LSI = 38KHz */
- IWDG_SetPrescaler(IWDG_Prescaler_128);////>510ms
-
- /* IWDG timeout equal to 214.7 ms (the timeout may varies due to LSI frequency dispersion) */
- /* IWDG timeout = (RELOAD_VALUE + 1) * Prescaler / LSI
- = (254 + 1) * 32 / 38 000
- = 214.7 ms */
- IWDG_SetReload((uint8_t)RELOAD_VALUE);
-
- /* Reload IWDG counter */
- IWDG_ReloadCounter();
- }
- void IWatchdogReset()
- {
- /* IWDG Configuration */
- IWDG_Config();
-
- while(1);///////////等待reset
- #if 0
- while (1)
- {
- /* Reload IWDG counter */
- IWDG_ReloadCounter();
- }
- #endif
- }
- void SoftReset_AtFirstTimeStartup(void)
- {
- uint32_t startadd = FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS;// + (uint16_t)FLASH_BLOCK_SIZE;
- if(FLASH_ReadByte(startadd) != 0xfb)/////////如果没有写过0xfa,写入0xfa,并reset
- {
- /* Define flash programming Time*/
- FLASH_SetProgrammingTime(FLASH_ProgramTime_Standard);
- /* Unlock flash data eeprom memory */
- FLASH_Unlock(FLASH_MemType_Data);
- /* Wait until Data EEPROM area unlocked flag is set*/
- while (FLASH_GetFlagStatus(FLASH_FLAG_DUL) == RESET)
- {}
- FLASH_ProgramByte(startadd,(uint8_t)(0xfb));///////不用擦,直接写
- FLASH_Lock(FLASH_MemType_Data);/////锁定
-
- IWatchdogReset();//////通过watchdog 软reset
- }
- /* Check if the system has resumed from IWDG reset */
- if (RST_GetFlagStatus(RST_FLAG_IWDGF) != RESET)//////////////检查是否有watchdog reset的flag。去掉
- {
- /* IWDGF flag set */
- /* Clear IWDGF Flag */
- RST_ClearFlag(RST_FLAG_IWDGF);
- #ifdef DEBUG
- printf_string("Reset by watchdog\n");
- #endif
- }
- else
- {
- /* IWDGF flag is not set */
- #ifdef DEBUG
- printf_string("Normal reset\n");
- #endif
- }
- }
- ///////////////////////////////////////////////////////////////
- void IWDG_test(void)
- {
- printf_string("reset\n");
- IWDG_ReloadCounter();
- while(1)
- {
- testpin(1);
- delay_us(102660);////////max delay_us(102660) == 840ms
- IWDG_ReloadCounter();
- testpin(0);
- delay_us(102660);
- IWDG_ReloadCounter();
- }
- }
- //**********************************************************
- uint8_t SPIx_ReadWriteByte(uint8_t dat)///////////sw spi
- {
- uint8_t i = 0;
- uint8_t temp = 0;
- //uint8_t b = 0;
- SCLK_L;//GPIOSetValue(PORT0,6,0);//GPIO_ResetBits(GPIOB, GPIO_Pin_0); //SCK=0
- delay_us(2);
- for(i=0;i<8;i++)
- {
- if(dat&0x80) //1000,0000;输出1
- {
- MOSI_H;//GPIOSetValue(PORT0,9,1);//GPIO_SetBits(GPIOB, GPIO_Pin_1); //MOSI=1
- }
- else
- {
- MOSI_L;//GPIOSetValue(PORT0,9,0);//GPIO_ResetBits(GPIOB, GPIO_Pin_1); //MOSI=0
- }
- dat = (dat << 1); //串行输出
- temp = (temp << 1); //串行输入
- //if(LPC_GPIO0->DATA&(1<<8))
- if((GPIOB->IDR & (uint8_t)GPIO_Pin_2)!=0)
- {
- temp++; //读入1
- }
- delay_us(2);
- SCLK_H;////GPIO_SetBits(GPIOB, GPIO_Pin_0); //SCK=1
- delay_us(2);
- SCLK_L;////GPIO_ResetBits(GPIOB, GPIO_Pin_0); //SCK=0
- }
- return temp; //返回读入的数据
- }
- void LED_onoff(uint8_t led,uint8_t onoff)
- {
- uint8_t led_light = 0x00;
-
- switch(led)
- {
- case 0:
- if(onoff == 1)
- {
- led_light |= 0x01;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x01);///断电
- }
- break;
- case 1:
- if(onoff == 1)
- {
- led_light |= 0x02;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x02);///断电
- }
- break;
- case 2:
- if(onoff == 1)
- {
- led_light |= 0x04;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x04);///断电
- }
- break;
- case 3:
- if(onoff == 1)
- {
- led_light |= 0x08;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x08);///断电
- }
- break;
- case 4:
- if(onoff == 1)
- {
- led_light |= 0x10;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x10);///断电
- }
- break;
- case 5:
- if(onoff == 1)
- {
- led_light |= 0x20;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x20);///断电
- }
- break;
- case 6:
- if(onoff == 1)
- {
- led_light |= 0x40;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x40);///断电
- }
- break;
- case 7:
- if(onoff == 1)
- {
- led_light |= 0x80;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0x80);///断电
- }
- break;
- case 8:
- if(onoff == 1)
- {
- led_light |= 0xff;// GPIO_ResetBits(GPIOB, GPIO_Pin_0);///通电
- }
- else
- {
- led_light &= (~0xff);///断电
- }
- break;
- default:
- break;
-
- }
- GPIOB->ODR = (~led_light);////低电平为开2017-03-02
- }
- //**********************************************************
- uint8_t ParallelPort_in(void)
- {
- uint8_t value = 0x00;
- if ((GPIOA->IDR & (uint8_t)GPIO_Pin_3)!=0)//(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3));///0
- {
- value|= 0x01;
- }
- if((GPIOA->IDR & (uint8_t)GPIO_Pin_2)!=0)//(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2));///1
- {
- value|= 0x02;
- }
- if((GPIOC->IDR & (uint8_t)GPIO_Pin_6)!=0)//(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6));///2
- {
- value|= 0x04;
- }
- if((GPIOC->IDR & (uint8_t)GPIO_Pin_5)!=0)//(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5));///3
- {
- value|= 0x08;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
818A的八位电容触摸按键方案_PDF_C97370_2017-03-10.7z
(13.16 MB, 下载次数: 238)
|