找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1885|回復(fù): 10
收起左側(cè)

單片機(jī)LED每過一段時(shí)間會出現(xiàn)頻閃求大佬指點(diǎn)解決?

[復(fù)制鏈接]
ID:757219 發(fā)表于 2023-3-27 22:12 | 顯示全部樓層 |閱讀模式
1.png
1.png
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-27 22:13 | 顯示全部樓層
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
#include "lcd016.h"

#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
#define LCD_Data_Port P0

sbit ADCS=P1^0;
sbit ADCLK=P1^1;
sbit ADDI=P1^2;
sbit ADDO=P1^2;
sbit LED=P1^4;

uint dat = 0x00;      //AD值
uchar adc=0;//存儲adc0832值
uint voltage = 0;
uchar pwm=0;//PWM占空比參數(shù)
uchar time=0;
uchar LED_buffer1[16] = {"ADC:000LX"};//ADC顯示緩沖
uchar LED_buffer2[16] = {"voltage:0.00V"};//電壓顯示緩沖
/*------------------------------------------------
延時(shí)函數(shù),含有輸入?yún)?shù) unsigned int t,無返回值
unsigned int 是定義無符號整形變量,其值的范圍是
0~65535
------------------------------------------------*/
void Delay(unsigned int t)
{
while(--t);
}



// 從ADC讀取數(shù)據(jù)的函數(shù)
uchar ADC_read_data(unsigned char channel)
{
unsigned char i = 0;
    unsigned char j;
    unsigned int dat = 0;
    unsigned char ndat = 0;

    if (channel == 0) channel = 2;//通道1
    if (channel == 1) channel = 3;//通道2
    ADDI = 1;//輸入引腳拉高
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCS = 0;//片選
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 1;//拉高時(shí)鐘
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 0;//拉低時(shí)鐘
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 1;//拉高時(shí)鐘
    ADDI = channel & 0x1;
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 0;//拉低時(shí)鐘
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 1;//拉高時(shí)鐘
    ADDI = (channel >> 1) & 0x1;
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    ADCLK = 0;//拉低時(shí)鐘
    ADDI = 1;//輸出1
    _nop_();//延時(shí)1us
    _nop_();//延時(shí)1us
    dat = 0; //存儲清零
    for (i = 0; i < 8; i++)    //循環(huán)8次
    {
        dat |= ADDO;//讀取引腳
        ADCLK = 1; //拉高時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 0;//拉低時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        dat <<= 1;//左移   最低位從外面進(jìn)去,最高位往左頂依舊是最高位  即0832數(shù)據(jù)最高位先進(jìn)去
        if (i == 7) dat |= ADDO;//讀取引腳
    }
    for (i = 0; i < 8; i++)//循環(huán)8次
    {
        j = 0;
        j = j | ADDO; //讀取引腳
        ADCLK = 1;    //拉高時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 0;    //拉低時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        j = j << 7;    //左移7位
        ndat = ndat | j; //合并數(shù)據(jù)
        if (i < 7) ndat >>= 1;//去掉符號
    }
    ADCS = 1; //清除片選
    ADCLK = 0;//拉低時(shí)鐘
    ADDO = 1; //輸出1
    dat <<= 8;//數(shù)據(jù)移位
    dat |= ndat;//合并數(shù)據(jù)
    return(ndat);
}


void init_timer1()//定時(shí)器1的初始化函數(shù)
{
TMOD|=0X11;  //設(shè)置計(jì)時(shí)器1為工作模式1,計(jì)時(shí)器0為工作模式1
    TH1=0X3c;    //設(shè)置計(jì)時(shí)器1的計(jì)數(shù)器高位為0x3C,讓定時(shí)器1產(chǎn)生一個(gè)50ms的中斷信號
    TL1=0XB0;    //設(shè)置計(jì)時(shí)器1的計(jì)數(shù)器低位為0xB0
    ET1=1;       //打開定時(shí)器1中斷允許
    EA=1;        //打開總中斷
    TR1=1;       //打開計(jì)時(shí)器1,若是定時(shí)器0則是TH0\TL0\ET0\TR0\TMOD=0X01
}

void main()
{
uchar i=0;
LCD_Init(); // 初始化LCD
init_timer1();
while (1)
{
        if(i<100) //輸出PWM調(diào)光,將一個(gè)周期具體化為100等分,從而易得高電平多少分來計(jì)算pwm
            i++;//不斷自增代表對一個(gè)周期100等分中每個(gè)等分進(jìn)行檢查此時(shí)是高電平還是低電平。在這100中方波越疏越暗,越密越亮。
        else
            i=0;
        if(i<84)
            LED=0;
        else
            LED=1;
}

}

//定時(shí)器1中斷函數(shù)
void Timer1() interrupt 3
{   
    if(time<8)
        time++;
    else
    {
    adc = ADC_read_data(0);//讀取adc值
    voltage = adc * 500.0 / 255;//將adc值換算成電壓
    LED_buffer1[4] = adc / 100 + '0';        //取adc百位
    LED_buffer1[5] = adc % 100 / 10 + '0';    //取adc十位
    LED_buffer1[6] = adc % 10 + '0';        //取adc個(gè)位
    LED_buffer2[8] = voltage / 100 + '0';        //取電壓個(gè)位
    LED_buffer2[9] = '.';//小數(shù)點(diǎn)
    LED_buffer2[10] = voltage / 10 % 10 + '0';    //取電壓十分位
    LED_buffer2[11] = voltage % 10 + '0';    //取電壓百分位
    LCD_ShowString(1, 1, &LED_buffer1[0]);    //顯示字符串
    LCD_ShowString(2, 1, &LED_buffer2[0]);    //顯示字符串
    }
    TH1 = 0x3C;     // 設(shè)置定時(shí)器1計(jì)數(shù)初值,用于控制LED亮度的PWM值
    TL1 = 0xB0;     // 設(shè)置定時(shí)器1計(jì)數(shù)初值,用于控制LED亮度的PWM值
}

不看其他只看P14口的led,正常應(yīng)該經(jīng)過pwm調(diào)制后led燈是暗的(圖3),但圖2是閃一下暗的然后常亮。
發(fā)現(xiàn)是正常的p14口高低電平交替輸出,不正常的是一直是低電平。
可是我用的代碼是一模一樣的,不知道哪里出問題了
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-27 22:14 | 顯示全部樓層
每過一段時(shí)間會頻閃,代碼已貼上求指點(diǎn)如何更改
回復(fù)

使用道具 舉報(bào)

ID:1004920 發(fā)表于 2023-3-28 13:09 | 顯示全部樓層
這程序?qū)懙挠纺[,AD采集最好不要放在中斷里。低電平點(diǎn)亮LED,調(diào)試先看看單一功能:AD的值對不對,定時(shí)器運(yùn)行時(shí)間,LED點(diǎn)亮等。都沒問題了再合起來。
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-28 17:54 | 顯示全部樓層
zch5200 發(fā)表于 2023-3-28 13:09
這程序?qū)懙挠纺[,AD采集最好不要放在中斷里。低電平點(diǎn)亮LED,調(diào)試先看看單一功能:AD的值對不對,定時(shí)器運(yùn) ...

ad采集放在主函數(shù)里led的頻閃會更嚴(yán)重直接出現(xiàn)頻閃
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-28 20:02 | 顯示全部樓層
有沒有大神幫忙修改一下,如何解決頻閃,led亮度隨adc控制的pwm變化
回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2023-3-29 00:40 | 顯示全部樓層
1:LED顯示的延時(shí)一定要均勻,2mS和500uS的延時(shí)幾乎是沒有區(qū)別的
2:不能有一個(gè)突變的延時(shí),比如,你LED的延時(shí)一直是1mS,ADC的時(shí)候,延時(shí)突然變成了2mS,這個(gè)時(shí)候是一定會閃的
解決建議:
LED顯示用定時(shí)器中斷掃描顯示,這樣就不會被ADC打斷了
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-29 16:02 | 顯示全部樓層
Y_G_G 發(fā)表于 2023-3-29 00:40
1:LED顯示的延時(shí)一定要均勻,2mS和500uS的延時(shí)幾乎是沒有區(qū)別的
2:不能有一個(gè)突變的延時(shí),比如,你LED的延時(shí) ...

我把led程序和adc讀取顯示兩個(gè)程序調(diào)換,即led顯示程序放入中斷后,led直接常亮了
回復(fù)

使用道具 舉報(bào)

ID:757219 發(fā)表于 2023-3-29 16:05 | 顯示全部樓層
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
#include "lcd016.h"

#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
#define LCD_Data_Port P0

sbit ADCS=P1^0;
sbit ADCLK=P1^1;
sbit ADDI=P1^2;
sbit ADDO=P1^2;
sbit LED=P1^4;

uint dat = 0x00;      //AD值
uchar adc=0;//存儲adc0832值
uint voltage = 0;
uchar pwm=0;//PWM占空比參數(shù)
uchar time=0;
uchar LED_buffer1[16] = {"ADC:000LX"};//ADC顯示緩沖
uchar LED_buffer2[16] = {"voltage:0.00V"};//電壓顯示緩沖
uchar adc2[4];
uchar voltage2[4];
/*------------------------------------------------
延時(shí)函數(shù),含有輸入?yún)?shù) unsigned int t,無返回值
unsigned int 是定義無符號整形變量,其值的范圍是
0~65535
------------------------------------------------*/
void Delay(unsigned int t)
{
while(--t);
}



// 從ADC讀取數(shù)據(jù)的函數(shù)
uchar ADC_read_data(unsigned char channel)
{
unsigned char i = 0;
        unsigned char j;
        unsigned int dat = 0;
        unsigned char ndat = 0;

        if (channel == 0) channel = 2;//通道1
        if (channel == 1) channel = 3;//通道2
        ADDI = 1;//輸入引腳拉高
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCS = 0;//片選
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 1;//拉高時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 0;//拉低時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 1;//拉高時(shí)鐘
        ADDI = channel & 0x1;
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 0;//拉低時(shí)鐘
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 1;//拉高時(shí)鐘
        ADDI = (channel >> 1) & 0x1;
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        ADCLK = 0;//拉低時(shí)鐘
        ADDI = 1;//輸出1
        _nop_();//延時(shí)1us
        _nop_();//延時(shí)1us
        dat = 0; //存儲清零
        for (i = 0; i < 8; i++)        //循環(huán)8次
        {
                dat |= ADDO;//讀取引腳
                ADCLK = 1; //拉高時(shí)鐘
                _nop_();//延時(shí)1us
                _nop_();//延時(shí)1us
                ADCLK = 0;//拉低時(shí)鐘
                _nop_();//延時(shí)1us
                _nop_();//延時(shí)1us
                dat <<= 1;//左移   最低位從外面進(jìn)去,最高位往左頂依舊是最高位  即0832數(shù)據(jù)最高位先進(jìn)去
                if (i == 7) dat |= ADDO;//讀取引腳
        }
        for (i = 0; i < 8; i++)//循環(huán)8次
        {
                j = 0;
                j = j | ADDO; //讀取引腳
                ADCLK = 1;        //拉高時(shí)鐘
                _nop_();//延時(shí)1us
                _nop_();//延時(shí)1us
                ADCLK = 0;        //拉低時(shí)鐘
                _nop_();//延時(shí)1us
                _nop_();//延時(shí)1us
                j = j << 7;        //左移7位
                ndat = ndat | j; //合并數(shù)據(jù)
                if (i < 7) ndat >>= 1;//去掉符號
        }
        ADCS = 1; //清除片選
        ADCLK = 0;//拉低時(shí)鐘
        ADDO = 1; //輸出1
        dat <<= 8;//數(shù)據(jù)移位
        dat |= ndat;//合并數(shù)據(jù)
        return(ndat);
}


void init_timer1()//定時(shí)器1的初始化函數(shù)
{
TMOD|=0X01;  //設(shè)置計(jì)時(shí)器1為工作模式1,計(jì)時(shí)器0為工作模式1
    TH0=0X3c;    //設(shè)置計(jì)時(shí)器1的計(jì)數(shù)器高位為0x3C,讓定時(shí)器1產(chǎn)生一個(gè)50ms的中斷信號
    TL0=0XB0;    //設(shè)置計(jì)時(shí)器1的計(jì)數(shù)器低位為0xB0
    ET0=1;       //打開定時(shí)器1中斷允許
    EA=1;        //打開總中斷
    TR0=1;       //打開計(jì)時(shí)器1,若是定時(shí)器0則是TH0\TL0\ET0\TR0\TMOD=0X01
}

void main()
{

LCD_Init(); // 初始化LCD
init_timer1();
while (1)
{
                adc = ADC_read_data(0);//讀取adc值
        voltage = adc * 500.0 / 255;//將adc值換算成電壓
        LED_buffer1[4] = adc / 100 + '0';                //取adc百位
        LED_buffer1[5] = adc % 100 / 10 + '0';        //取adc十位
        LED_buffer1[6] = adc % 10 + '0';                //取adc個(gè)位
        LED_buffer2[8] = voltage / 100 + '0';                //取電壓個(gè)位
        LED_buffer2[9] = '.';//小數(shù)點(diǎn)
        LED_buffer2[10] = voltage / 10 % 10 + '0';        //取電壓十分位
        LED_buffer2[11] = voltage % 10 + '0';        //取電壓百分位
        LCD_ShowString(1, 1, LED_buffer1);        //顯示字符串
        LCD_ShowString(2, 1, LED_buffer2);        //顯示字符串

}

}

//定時(shí)器1中斷函數(shù)
void Timer1() interrupt 1
{       
        uchar i;
          pwm=adc/2;
                if(i<100) //輸出PWM調(diào)光,將一個(gè)周期具體化為100等分,從而易得高電平多少分來計(jì)算pwm
                        i++;//不斷自增代表對一個(gè)周期100等分中每個(gè)等分進(jìn)行檢查此時(shí)是高電平還是低電平。在這100中方波越疏越暗,越密越亮。
                else
                        i=0;
                if(i<84)
                        LED=0;
                else
                        LED=1;

    TH0 = 0x3C;     // 設(shè)置定時(shí)器1計(jì)數(shù)初值,用于控制LED亮度的PWM值
    TL0 = 0xB0;     // 設(shè)置定時(shí)器1計(jì)數(shù)初值,用于控制LED亮度的PWM值
}


這樣改似乎程序進(jìn)入不了中斷了
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表