久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1696|回復: 10
打印 上一主題 下一主題
收起左側

單片機LED每過一段時間會出現頻閃求大佬指點解決?

[復制鏈接]
跳轉到指定樓層
樓主

1.png (75.13 KB, 下載次數: 35)

1.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:757219 發表于 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占空比參數
uchar time=0;
uchar LED_buffer1[16] = {"ADC:000LX"};//ADC顯示緩沖
uchar LED_buffer2[16] = {"voltage:0.00V"};//電壓顯示緩沖
/*------------------------------------------------
延時函數,含有輸入參數 unsigned int t,無返回值
unsigned int 是定義無符號整形變量,其值的范圍是
0~65535
------------------------------------------------*/
void Delay(unsigned int t)
{
while(--t);
}



// 從ADC讀取數據的函數
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_();//延時1us
    _nop_();//延時1us
    ADCS = 0;//片選
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 1;//拉高時鐘
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 0;//拉低時鐘
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 1;//拉高時鐘
    ADDI = channel & 0x1;
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 0;//拉低時鐘
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 1;//拉高時鐘
    ADDI = (channel >> 1) & 0x1;
    _nop_();//延時1us
    _nop_();//延時1us
    ADCLK = 0;//拉低時鐘
    ADDI = 1;//輸出1
    _nop_();//延時1us
    _nop_();//延時1us
    dat = 0; //存儲清零
    for (i = 0; i < 8; i++)    //循環8次
    {
        dat |= ADDO;//讀取引腳
        ADCLK = 1; //拉高時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 0;//拉低時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        dat <<= 1;//左移   最低位從外面進去,最高位往左頂依舊是最高位  即0832數據最高位先進去
        if (i == 7) dat |= ADDO;//讀取引腳
    }
    for (i = 0; i < 8; i++)//循環8次
    {
        j = 0;
        j = j | ADDO; //讀取引腳
        ADCLK = 1;    //拉高時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 0;    //拉低時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        j = j << 7;    //左移7位
        ndat = ndat | j; //合并數據
        if (i < 7) ndat >>= 1;//去掉符號
    }
    ADCS = 1; //清除片選
    ADCLK = 0;//拉低時鐘
    ADDO = 1; //輸出1
    dat <<= 8;//數據移位
    dat |= ndat;//合并數據
    return(ndat);
}


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

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

}

//定時器1中斷函數
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個位
    LED_buffer2[8] = voltage / 100 + '0';        //取電壓個位
    LED_buffer2[9] = '.';//小數點
    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;     // 設置定時器1計數初值,用于控制LED亮度的PWM值
    TL1 = 0xB0;     // 設置定時器1計數初值,用于控制LED亮度的PWM值
}

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

使用道具 舉報

板凳
ID:757219 發表于 2023-3-27 22:14 | 只看該作者
每過一段時間會頻閃,代碼已貼上求指點如何更改
回復

使用道具 舉報

地板
ID:1004920 發表于 2023-3-28 13:09 | 只看該作者
這程序寫的臃腫,AD采集最好不要放在中斷里。低電平點亮LED,調試先看看單一功能:AD的值對不對,定時器運行時間,LED點亮等。都沒問題了再合起來。
回復

使用道具 舉報

5#
ID:757219 發表于 2023-3-28 17:54 | 只看該作者
zch5200 發表于 2023-3-28 13:09
這程序寫的臃腫,AD采集最好不要放在中斷里。低電平點亮LED,調試先看看單一功能:AD的值對不對,定時器運 ...

ad采集放在主函數里led的頻閃會更嚴重直接出現頻閃
回復

使用道具 舉報

6#
ID:757219 發表于 2023-3-28 20:02 | 只看該作者
有沒有大神幫忙修改一下,如何解決頻閃,led亮度隨adc控制的pwm變化
回復

使用道具 舉報

7#
ID:401564 發表于 2023-3-29 00:40 | 只看該作者
1:LED顯示的延時一定要均勻,2mS和500uS的延時幾乎是沒有區別的
2:不能有一個突變的延時,比如,你LED的延時一直是1mS,ADC的時候,延時突然變成了2mS,這個時候是一定會閃的
解決建議:
LED顯示用定時器中斷掃描顯示,這樣就不會被ADC打斷了
回復

使用道具 舉報

8#
ID:757219 發表于 2023-3-29 16:02 | 只看該作者
Y_G_G 發表于 2023-3-29 00:40
1:LED顯示的延時一定要均勻,2mS和500uS的延時幾乎是沒有區別的
2:不能有一個突變的延時,比如,你LED的延時 ...

我把led程序和adc讀取顯示兩個程序調換,即led顯示程序放入中斷后,led直接常亮了
回復

使用道具 舉報

9#
ID:757219 發表于 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占空比參數
uchar time=0;
uchar LED_buffer1[16] = {"ADC:000LX"};//ADC顯示緩沖
uchar LED_buffer2[16] = {"voltage:0.00V"};//電壓顯示緩沖
uchar adc2[4];
uchar voltage2[4];
/*------------------------------------------------
延時函數,含有輸入參數 unsigned int t,無返回值
unsigned int 是定義無符號整形變量,其值的范圍是
0~65535
------------------------------------------------*/
void Delay(unsigned int t)
{
while(--t);
}



// 從ADC讀取數據的函數
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_();//延時1us
        _nop_();//延時1us
        ADCS = 0;//片選
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 1;//拉高時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 0;//拉低時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 1;//拉高時鐘
        ADDI = channel & 0x1;
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 0;//拉低時鐘
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 1;//拉高時鐘
        ADDI = (channel >> 1) & 0x1;
        _nop_();//延時1us
        _nop_();//延時1us
        ADCLK = 0;//拉低時鐘
        ADDI = 1;//輸出1
        _nop_();//延時1us
        _nop_();//延時1us
        dat = 0; //存儲清零
        for (i = 0; i < 8; i++)        //循環8次
        {
                dat |= ADDO;//讀取引腳
                ADCLK = 1; //拉高時鐘
                _nop_();//延時1us
                _nop_();//延時1us
                ADCLK = 0;//拉低時鐘
                _nop_();//延時1us
                _nop_();//延時1us
                dat <<= 1;//左移   最低位從外面進去,最高位往左頂依舊是最高位  即0832數據最高位先進去
                if (i == 7) dat |= ADDO;//讀取引腳
        }
        for (i = 0; i < 8; i++)//循環8次
        {
                j = 0;
                j = j | ADDO; //讀取引腳
                ADCLK = 1;        //拉高時鐘
                _nop_();//延時1us
                _nop_();//延時1us
                ADCLK = 0;        //拉低時鐘
                _nop_();//延時1us
                _nop_();//延時1us
                j = j << 7;        //左移7位
                ndat = ndat | j; //合并數據
                if (i < 7) ndat >>= 1;//去掉符號
        }
        ADCS = 1; //清除片選
        ADCLK = 0;//拉低時鐘
        ADDO = 1; //輸出1
        dat <<= 8;//數據移位
        dat |= ndat;//合并數據
        return(ndat);
}


void init_timer1()//定時器1的初始化函數
{
TMOD|=0X01;  //設置計時器1為工作模式1,計時器0為工作模式1
    TH0=0X3c;    //設置計時器1的計數器高位為0x3C,讓定時器1產生一個50ms的中斷信號
    TL0=0XB0;    //設置計時器1的計數器低位為0xB0
    ET0=1;       //打開定時器1中斷允許
    EA=1;        //打開總中斷
    TR0=1;       //打開計時器1,若是定時器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個位
        LED_buffer2[8] = voltage / 100 + '0';                //取電壓個位
        LED_buffer2[9] = '.';//小數點
        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);        //顯示字符串

}

}

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

    TH0 = 0x3C;     // 設置定時器1計數初值,用于控制LED亮度的PWM值
    TL0 = 0xB0;     // 設置定時器1計數初值,用于控制LED亮度的PWM值
}


這樣改似乎程序進入不了中斷了
回復

使用道具 舉報

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

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人免费看片网 | 亚洲一区欧美 | 亚洲视频区 | 少妇无套高潮一二三区 | 久久九九网站 | 国产欧美精品一区二区色综合朱莉 | 羞羞的视频免费在线观看 | 一二三区av | 亚洲激情综合 | 性色网站| 91偷拍精品一区二区三区 | www.亚洲精品 | 中文字幕的av | 国产在线观看网站 | 黄色网址av | 免费观看色 | 国产乱码精品一区二区三区忘忧草 | aaaa日韩 | 久久成人国产精品 | 亚洲有码转帖 | 91麻豆精品国产91久久久久久 | 日韩二三区 | 国产精品久久久久久久午夜片 | 国产极品91 | 91av视频 | 韩日在线视频 | 在线国产一区 | 波多野吉衣在线播放 | 嫩草影院网址 | 国产区精品 | 久久九精品 | 粉嫩一区二区三区国产精品 | 欧美一a一片一级一片 | 91在线视频观看免费 | 婷婷免费在线 | 久久精品91久久久久久再现 | 精品国产鲁一鲁一区二区张丽 | 欧美日韩亚洲二区 | 毛片黄片免费看 | 国产精品一区二区三区四区 | 国产一区二区视频免费在线观看 |