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 + -
显示快捷键?