pwmtoadc_t0定时中断4位数码管扫描显示.c

来自「输出脉冲后模数转换器检测到后送定时中断4位数码管扫描显示」· C语言 代码 · 共 106 行

C
106
字号
// PWM0输出到ADC_定时中断4位数码管扫描显示.c  T0 定时中断;  P1口段笔画,  0=亮;  P2口低4位作位选, 0=选中
#include <STC12C5410AD.H>   // 单片机内部专用寄存器定义
sbit K1= P3^0;  // 键K1输入引脚定义
 bit K1_b;      // 前次键K1输入状态
sbit K2= P3^1;  // 键K2输入引脚定义
 bit K2_b;      // 前次键K2输入状态
unsigned char  plus  =0xC0;  // PWM 脉冲宽度. 值越大,脉冲宽度(高电平)越窄. 0xC0=25%佔空比
//-----------------------------------------
unsigned  int  adc=0;  // 保存10位AD转换结果

/* T0_int 定时 时间常数 5ms=5000=1388H->EC78H     f=12MH */
/*                      5ms=4608=1200H->EE00H     f=11.0592MH */
#define  time_5ms_H  0xEE       /* t=5ms for T0_INT_timer  */
#define  time_5ms_L  0x00

code unsigned char seg_tab[16]={  /* 显示段笔划 hgfedcba; 0=亮 */
  0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,  /* 0,1,2,3,4,5,6,7,8,9 */
  0x88,0x83,0xC6,0xA1,0x86,0x8E};   // A b C d E F
unsigned char  led_buff[4];     /* 存放4位数码管的段笔画 */

void delay(unsigned int i) { for(;i!=0;i--); }
unsigned char  led_p=0;         /* 待显示的位 */

// 将一整形量的值以4位10进制数显示的段笔划送显示缓冲区 
void led_fill_d(unsigned int n)
{ led_buff[3]=seg_tab[(unsigned char)(n%10)];  // 个位
  n=n/10;
  led_buff[2]=seg_tab[(unsigned char)(n%10)];  // 十位
  n=n/10;
  led_buff[1]=seg_tab[(unsigned char)(n%10)];  // 百位
  n=n/10;
  led_buff[0]=seg_tab[(unsigned char)(n%10)];  // 千位
}

//显示一位。b=0,1,2,3 第几位显示指定
void shrow_1LED(unsigned char b) 
{	P2 = P2 | 0x0F;         // P2 口 LED 全灭. 0=亮
  P1 = led_buff[b];       // 送段信号 
  P2 = P2 & (~(0x01<<b)); // 位选中, 该位亮
}
main()
{	
  // PWM --------
     CMOD = 0x02; // 计数脉冲源选择= 0 1   f/2 。 11.0592M/2/256=21.6KHz
     CL = 0x00;
     CH = 0x00;
       // PCA_PWM0=0;  // 可以输出PWM.
       // PCA_PWM0=3;  // PWM 输出就一直是 0, 无脉冲。 可起到关闭PWM输出功能作用.
     CCAP0L = plus;  //Set the initial value same as CCAP0H
                     // 0_CL(计数值) <  EPCnL_CCAPnL(设定值) :  输出=0
                     // 0_CL         >= EPCnL_CCAPnL          :  输出=1
     CCAP0H = plus;  // CL 溢出时, CCAP0L=CCAP0H; (自动重装). 所以 CCAP0H 中, 设的置越大,脉冲宽度(高电平)越窄
     CCAPM0 = 0x42;  //0100,0010 Setup PCA module 0 in PWM mode
     CR = 1;         //Start PCA Timer. PWM开始工作了
  // T0--------
   TMOD= 0x11;       /* 0001$0001 T1 & T0 are 16bit timers */
   TH0 = time_5ms_H; /* T0 timer 5ms  */
   TL0 = time_5ms_L;
                     /* TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0  */
   TCON= 0x10;       /*  0   0   0   1   0   0   0   0   */
                     /*        start T0    xint1   xint0 */
   IE= 0x82;         /* 1000 0010,  EA=ET0=1,  */
  // ADC-------
   P1M0 |= 0x0FF;     // P1.0 P1.1设为高阻输入.  用于AD输入
   ADC_CONTR= 0x80;   // A/D 转换控制寄存器 ADC_POWER SPEED1_SPEED0 ADC_FLAG ADC_START CHS2_CHS1_CHS0
     // 启动ADC转换, 0通道
   ADC_CONTR= 0x80;  //  *ADC_POWER SPEED1_SPEED0 ADC_FLAG *ADC_START CHS2_CHS1_CHS0
 
	while (1)    // 死循环
	{ 
  	delay(10000);     //软延时
		led_fill_d(adc);  // 数 填入显示缓冲区
	}
}
//==========================================
/*===================================*/
/* T0 中断服务程序[5MS定时中断一次] */
/*===================================*/
void T0_ISR() interrupt 1     /* T0 Interrupt 1 */
{
   TL0= time_5ms_L;     // 重置5MS时间常数
   TH0= time_5ms_H;
// 1. 扫描输出一位LED
   shrow_1LED(led_p);   // 第led_p位亮
   led_p=(led_p+1)%4;   // 指向下一位, 为下一次中断显示用
// 2. 读ADC转换结果  
     //  while ((ADC_CONTR & 0x10)==0);  // 等待ADC转换结束
   adc = ADC_DATA;   // ADC 高8位
   adc = (adc<<2) + (ADC_LOW2 &0x3); // 10位ADC结果
     // 启动下一次ADC转换, 0通道
   ADC_CONTR= 0x80;  //  *ADC_POWER SPEED1_SPEED0 ADC_FLAG *ADC_START CHS2_CHS1_CHS0
// 3.采样按键
	   if ((K1==0) && (K1_b==1) && (plus!=0))  // 按键新按下且不是最大输出
	   {
	   	 plus_t--;        // 增加脉宽
	     CCAP0H = plus;   // 更新,改变PWM
	   }
	   K1_b=K1;
	   if ((K2==0) && (K2_b==1) && (plus!=0xFF)) // 按键新按下且不是最小输出
	   {
	   	 plus_t++;        // 减小脉宽
	     CCAP0H = plus;   // 更新,改变PWM
	   }
	   K2_b=K2;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?