這里分享一個前一段時間寫的一個單片機程序。程序的主要功能是對鋰電池充放電模塊的鋰電池電壓和輸出電壓進行檢測,并將檢測后的電壓用數碼管進行顯示。
程序的主控芯片是STM8S103F3P。用的是下圖的最小系統板。
基本參數如下:
1、核心尺寸:8bit
2、速度:16MHz
3、連接性:12C,IrDA,LIN,SPI, UART/USART
4、外設:欠壓檢測/復位,POR,PWM,WDT
5、I/0數:16
6、程序存儲容量:8KB(8Kx8)
7、程序存儲器類型:閃存FLASH 可擦寫一萬次
8、EEPROM容量:640x8
9、RAM容量:1Kx8
10、電壓-電源(Vcc/Vdd): 2.95V~5.5V
11、數據轉換器:A/D 5x10b
12、振蕩器類型:內部
13、工作溫度:-40°C~85°C(TA)
數碼管顯示部分用的是TM1637驅動的數碼管模塊。該模塊是一個12腳的帶時鐘點的4位共陽數碼管(0.36英寸)的顯示模塊,驅動芯片為TM1637,只需2根信號線即可使單片機控制4位8段數碼管。
模塊特點如下: 顯示器件為4位共陽紅字數碼管; 數碼管8級灰度可調; 控制接口電平可為5V或3.3V; 4個M2螺絲定位孔,便于安裝。
數碼管模塊的: CLK引腳與PB4引腳相連; DIO引腳與PB5引腳相連。
由于本次使用的單片機的ADC部分為3.3V供電,而鋰電池電壓和輸出電壓都大于3.3V,所以這里通過串接電阻分壓的方式來實現電壓的檢測。程序中分別使用單片機ADC的通道2、通道3、通道4對輸入端電壓、鋰電池電壓及輸出端電壓進行檢測。
程序中利用單片機的定時器4進行采樣周期定時,采樣時間到后程序控制ADC進行電壓采集和計算,并進行了10次累加求平均值,最后將采集的電壓轉換為實際電壓進行顯示。
主程序部分如下:
?
/** ****************************************************************************** * @file Project/main.c * @author MCD Application Team * @version V2.1.0 * @date 18-November-2011 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * ******************************************************************************* */ /* Includes ------------------------------------------------------------------*/ #include "stm8s.h" #include "TM1637.h" #include "math.h" /* Private defines -----------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ //#define LED_GPIO_PORT (GPIOB) //#define LED_GPIO_PINS (GPIO_PIN_5) //定時電壓結構體 typedef struct { float in_vol ; float out_vol ; float bat_vol ; } voltage ; uint8_t ad_buf[10] ; uint16_t sleep_cnt = 0 ; void Init_ADC(void) { //GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_IN_FL_NO_IT); //單次掃描模式 /*ADC1_DeInit(); ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_2, ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL, ENABLE); ADC1_Cmd(ENABLE);*/ //連續掃描模式 ADC1_DeInit();//ADC 相關寄存器恢復默認值 //初始化 ADC:連續轉換/通道 8/時鐘分頻/關閉事件/數據右對齊/使能施密特觸發器 ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_5, ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,ENABLE);//該處在串口發送及接收時需配置為ENABLE,否則會出現無法發送的現象。 ADC1_ScanModeCmd(ENABLE); ADC1_Cmd(ENABLE);//使能 ADC } uint16_t i=0; uint8_t sample_flag = 0 ; uint8_t sample_cnt = 0 ; voltage m_state ; /* Private defines -----------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ void Init_GPIO(void) { GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST); } void Init_Timer4(void) { /*TIM4_UpdateDisableConfig(ENABLE);//允許更新事件 TIM4_ARRPreloadConfig(ENABLE);//自動重裝 TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);//中斷配置,更新中斷 TIM4_SetCounter(0xff);//計數器初值 TIM4_SetAutoreload(0xFF);//計數器自動重裝的初值 TIM4_PrescalerConfig(TIM4_PRESCALER_128, TIM4_PSCRELOADMODE_UPDATE);//預分頻值 */ TIM4_TimeBaseInit(TIM4_PRESCALER_128, 0x82); /* Clear TIM4 update flag */ TIM4_ClearFlag(TIM4_FLAG_UPDATE); /* Enable update interrupt */ TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE); TIM4_Cmd(ENABLE); } void main(void) { // ErrorStatus clk_return_status; //FlagStatus flag_status; u16 u16_adc1_value1 ; u16 u16_adc1_value2 ; u16 u16_adc1_value3 ; u16 display_cnt = 0 ; float last_input = 0 ; float last_output = 0 ; /* Configuration -----------------------------------------*/ CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//不分頻 CLK_HSICmd(ENABLE); //開始內部高頻RC Init_ADC(); Init_Timer4(); enableInterrupts(); GPIO_init(); //TM1637_display(0x00,0x00,0,0x00,0x01); sleep_cnt = 0 ; while (1) { if(sample_flag==1) { sample_flag = 0 ; /* ADC1_StartConversion(); flag_status = ADC1_GetFlagStatus(ADC1_FLAG_EOC); u16_adc1_value = ADC1_GetConversionValue();*/ ADC1_StartConversion();//開啟一次轉換 while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待轉換完成 ADC1_ClearFlag(ADC1_FLAG_EOC);//軟件清除 u16_adc1_value1+=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL2);//讀取AIN2的值 u16_adc1_value2+=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL3);//讀取AIN4的值 u16_adc1_value3+=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL4);//讀取AIN4的值 sample_cnt ++ ; if(sample_cnt>=10) { sample_cnt = 0 ; m_state.in_vol = (u16_adc1_value1 / 10)*0.03223*1.4545 ; m_state.out_vol = (u16_adc1_value2 / 10)*0.03223*3.2 ; m_state.bat_vol = (u16_adc1_value3 / 10)*0.03223*2 ; u16_adc1_value1 = 0 ; u16_adc1_value2 = 0 ; u16_adc1_value3 = 0 ; } display_cnt++; } if(display_cnt>999&&sleep_cnt < 10) { display_cnt=0; TM1637_display((int)m_state.bat_vol/10%10,(int)m_state.bat_vol%10,(int)m_state.out_vol/10%10,(int)m_state.out_vol%10,0x01); sleep_cnt ++ ; }else if(sleep_cnt>=9) { if(((last_output-m_state.out_vol)>0.5)||((m_state.in_vol-last_input)>0.8)) { sleep_cnt = 0 ; } last_input = m_state.in_vol ; last_output = m_state.out_vol ; TM1637_display(21,21,21,21,0); } } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval : None */ void assert_failed(u8* file, u32 line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d ", file, line) */ /* Infinite loop */ while (1) { } } #endif /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
© COPYRIGHT 2011 STMicroelectronics
?
審核編輯:劉清
評論