这里分享一个前一段时间写的一个单片机程序。程序的主要功能是对锂电池充放电模块的锂电池电压和输出电压进行检测,并将检测后的电压用数码管进行显示。
下图呢就是实际的显示效果,左侧是锂电池的电压,右侧是输出电压。
程序的主控芯片是STM8S103F3P。用的是下图的最小系统板。
基本参数如下:
1、核心尺寸:8bit
2、速度:16MHz
3、连接性:12C,IrDA,LIN,SPI, UART/USART4、外设:欠压检测/复位,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.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* 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\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
工程是基于IAR FOR STM创建的。