本帖最后由 zjut_zone 于 2015-4-3 12:00 编辑
这个程序是采集电压并用三位数码管显示的,程序方面没有系统的学习,请教程序架构改如何优化。
<div class="blockcode"><blockquote>/* MAIN.C file
* 电压采样并用三位数码管显示,单片机直接驱动
*/
#include<stm8s003f3.h>
#define N 10
const unsigned char LED1[]={0xA8,0x28,0x98,0xB8,0x38,0xB0,0xB0,0x28,0XBF,0XBF};
const unsigned char LED2[]={0x34,0x00,0x14,0x10,0x20,0x30,0x34,0x10,0XFF,0XFB};
unsigned int i,k,j,value;
unsigned int a;
unsigned char d=0;
unsigned int sum=0;
unsigned char adcbuf[9];
_Bool dot @PC_ODR:6;
//*三位数码管显示函数*//
void Display(unsigned char x)
{
for(i=0;i<200;i++);
PC_ODR = 0X00;
PD_ODR = 0X00;
if(++d>2)
{
d=0;
}
//*三位数码管十位显示范围1-2*//
if(d==0)
{
if(x/100==2)
{
PA_ODR = 0X0c; //共阴极数码管,显示第一位
PC_ODR = LED1[2]; //显示数字2,PC和PD共同控制
PD_ODR = LED2[2];
}
else if(x/100==1)
{
PA_ODR = 0X0c;
PC_ODR = LED1[1];
PD_ODR = LED2[1];
}
else
{
PA_ODR = 0X00;
}
}
//*三位数码管个位显示范围0-9和小数点*//
else if(d==1)
{
if(x/10%10==0)
{
PA_ODR = 0X0a; //共阴极数码管,显示第二位
PC_ODR = LED1[0];
PD_ODR = LED2[0];
dot=1; //显示小数点
}
else if(x/10%10==1)
{
PA_ODR = 0X0a;
PC_ODR = LED1[1];
PD_ODR = LED2[1];
dot=1;
}
else if(x/10%10==2)
{
PA_ODR = 0X0a;
PC_ODR = LED1[2];
PD_ODR = LED2[2];
dot=1;
}
else if(x/10%10==3)
{
PA_ODR = 0X0a;
PC_ODR = LED1[3];
PD_ODR = LED2[3];
dot=1;
}
else if(x/10%10==4)
{
PA_ODR = 0X0a;
PC_ODR = LED1[4];
PD_ODR = LED2[4];
dot=1;
}
else if(x/10%10==5)
{
PA_ODR = 0X0a;
PC_ODR = LED1[5];
PD_ODR = LED2[5];
dot=1;
}
else if(x/10%10==6)
{
PA_ODR = 0X0a;
PC_ODR = LED1[6];
PD_ODR = LED2[6];
dot=1;
}
else if(x/10%10==7)
{
PA_ODR = 0X0a;
PC_ODR = LED1[7];
PD_ODR = LED2[7];
dot=1;
}
else if(x/10%10==8)
{
PA_ODR = 0X0a;
PC_ODR = LED1[8];
PD_ODR = LED2[8];
dot=1;
}
else if(x/10%10==9)
{
PA_ODR = 0X0a;
PC_ODR = LED1[9];
PD_ODR = LED2[9];
dot=1;
}
}
//*小数点后面显示范围0-9*//
else
{
if(x%10==0)
{
PA_ODR = 0X06;
PC_ODR = LED1[0];
PD_ODR = LED2[0];
}
if(x%10==1)
{
PA_ODR = 0X06;
PC_ODR = LED1[1];
PD_ODR = LED2[1];
}
if(x%10==2)
{
PA_ODR = 0X06;
PC_ODR = LED1[2];
PD_ODR = LED2[2];
}
if(x%10==3)
{
PA_ODR = 0X06;
PC_ODR = LED1[3];
PD_ODR = LED2[3];
}
if(x%10==4)
{
PA_ODR = 0X06;
PC_ODR = LED1[4];
PD_ODR = LED2[4];
}
if(x%10==5)
{
PA_ODR = 0X06;
PC_ODR = LED1[5];
PD_ODR = LED2[5];
}
if(x%10==6)
{
PA_ODR = 0X06;
PC_ODR = LED1[6];
PD_ODR = LED2[6];
}
if(x%10==7)
{
PA_ODR = 0X06;
PC_ODR = LED1[7];
PD_ODR = LED2[7];
}
if(x%10==8)
{
PA_ODR = 0X06;
PC_ODR = LED1[8];
PD_ODR = LED2[8];
}
if(x%10==9)
{
PA_ODR = 0X06;
PC_ODR = LED1[9];
PD_ODR = LED2[9];
}
}
}
//*初始化ADC模块*//
void ADC_init(void)
{
ADC_CSR = 0x06; // 选择AD转换通道AN6
ADC_CR1 = 0X00; // 设置AD转换时钟1/2,1MHz;单次转换
ADC_CR2 = 0x08; // 设置数据为右对齐
ADC_CR3 = 0x00; // 不使用数据缓冲
ADC_TDRL = 0X01; // 禁止施密特触发
}
//*初始化IO口*//
void GPIO_init(void)
{
CLK_ICKR = 0X01; // 系统时钟默认内部RC16MHz;
CLK_CKDIVR = 0X18; //系统默认8分频;
PD_DDR = 0X34; //PD6--AN6.
PD_CR1 = 0X3F;
PD_CR2 = 0X00;
PD_ODR = 0Xff;
PC_DDR = 0XF8;
PC_CR1 = 0XFF;
PC_CR2 = 0X00;
PC_ODR = 0X00;
PA_DDR = 0X0E;
PA_CR1 = 0XFF;
PA_CR2 = 0X00;
PA_ODR = 0X00;
}
//*采集电压多组取平均值*//
unsigned int GetADC(void)
{
for(i=0;i<N;i++)
{
ADC_CSR &= 0x7F; //EOC位清零
while(!(ADC_CSR & 0x86)); // 等待AD转换完成,EOC自动置1
adcbuf[i] = ADC_DRH * 256 + ADC_DRL;
}
for(i=0;i<N;i++)
{
sum+=adcbuf[i];
}
sum=sum/N;
return sum;
}
void main(void)
{
GPIO_init();
ADC_init();
while (1)
{
ADC_CR1 = 0x01; // 打开AD模块电源
for (i = 0;i < 100;i++); // 延时
value=GetADC();
a =(int)(((float)value / 1023) * 5000);
a=(int)(((float)a / 30) * 1006);
a/=100;
Display(a);
}
}
|