導航:首頁 > 操作系統 > 51單片機編碼器程序

51單片機編碼器程序

發布時間:2023-05-11 15:28:19

『壹』 51單片機的一個簡單程序

ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
MOV A,P0

ANL A,#1EH

CJNE A,#02H,MAIN1

SETB P1.1

CLR P1.2

CLR P1.8

SJMP MAIN

MAIN1:
CJNE A,#04H,MAIN2

CLR P1.1

SETB P1.2

CLR P1.8

SJMP MAIN

MAIN2:
CJNE A,#1EH,MAIN3

CLR P1.1

CLR P1.2

SETB P1.8

SJMP MAIN

MAIN3:
CLR P1.1

CLR P1.2

CLR P1.8

LJMP MAIN

END

『貳』 51單片機利用外部中斷INT0和INT1實現編碼器雙向計數功能

分數給的太少了。我只能給你提供一個思路,然後你自已寫程序:
int0和int1分別對應單片機兩個不同的引腳,你要先在單片機復位時在特殊功能寄存器中來配置這兩個引腳的功能,int0和int1的中斷都分別有兩個功能,一個是計數器工作方式,一個是外部中斷工作方式。
你的這個要求是不能用int0和int1兩個引腳的計數器功能的,你只能用外部中斷功能。
然後定義好int0和int1分別在中斷時的跳轉地址,在程序進入中斷之後,分別在不同的中斷程序中對一個寄存器表示的計數器進行加1或者減1操作。
一定記得在處理中斷的時候,要把中斷使能的寄存器標置位關掉,以避免中斷重復執行和錯誤。

『叄』 怎麼用51單片機和編碼器判斷正反轉啊求51單片機的C程序,謝謝

編碼器的正轉與反轉的相位是用差別的,首先你要了解你使用的編碼器的正轉及反轉的相位。編程的方法有很多,比如可以用查詢IO口電平變化的方式去判斷

『肆』 51單片機程序編寫

/*這是用LCD顯示所測溫度的代碼,你參考一下,如果沒問題的話,其他的功能你再添加就好了,不難*/

#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

#define Nack_number 10

//**************埠定義**************************************************

uchar flag; //LCD控制線介面

sbit RS=P1^0; //RS端

sbit RW=P1^1; //讀寫端

sbit LCDE=P2^5; //使能端

//mlx90614埠定義

sbit SCK=P2^1; //時鍾線

sbit SDA=P2^2; //數據線

//************數據定義****************************************************

bdata uchar flag1; //可位定址數據

sbit bit_out=flag1^7;

sbit bit_in=flag1^0;

uchar tempH,tempL,err;


//************************** LCD1602 ***********************************

//向LCD寫入命令或數據*****************************************************

#define LCD_COMMAND 0 //命令

#define LCD_DATA 1 // 數據

#define LCD_CLEAR_SCREEN 0x01 // 清屏

#define LCD_HOMING 0x02 // 游標返回原點

//設置顯示模式******* 0x08+ *********************************************

#define LCD_SHOW 0x04 //顯示開

#define LCD_HIDE 0x00 //顯示關

#define LCD_CURSOR 0x02 //顯示游標

#define LCD_NO_CURSOR 0x00 //無游標

#define LCD_FLASH 0x01 //游標閃動

#define LCD_NO_FLASH 0x00 //游標不閃動

//設置輸入模式********** 0x04+ ********************************************

#define LCD_AC_UP 0x02 //游標右移 AC+

#define LCD_AC_DOWN 0x00 //默認 游標左移 AC-

#define LCD_MOVE 0x01 //畫面可平移

#define LCD_NO_MOVE 0x00 //默認 畫面不移動


//************************** mlx90614 ***********************************

//command mode 命令模式

#define RamAccess 0x00 //對RAM操作

#define EepomAccess 0x20 //對EEPRAM操作

#define Mode 0x60 //進入命令模式

#define ExitMode 0x61 //退出命令模式

#define ReadFlag 0xf0 //讀標志

#define EnterSleep 0xff //進入睡眠模式

//ram address read only RAM地址(只讀)

#define AbmientTempAddr 0x03 //周圍溫度

#define IR1Addr 0x04

#define IR2Addr 0x05

#define LineAbmientTempAddr 0x06 //環境溫度

/*0x0000 0x4074 16500 0.01/單元

-40 125*/

#define LineObj1TempAddr 0x07 //目標溫度,紅外溫度

/*0x27ad-0x7fff 0x3559 22610 0.02/單元

-70.01-382.19 0.01 452.2*/

#define LineObj2TempAddr 0x08

//eepom address EEPROM地址

#define TObjMaxAddr 0x00 //測量范圍上限設定

#define TObjMinAddr 0x01 //測量范圍下限設定

#define PWMCtrlAddr 0x02 //PWM設定

#define TaRangeAddr 0x03 //環境溫度設定

#define KeAddr 0x04 //頻率修正系數

#define ConfigAddr 0x05 //配置寄存器

#define SMbusAddr 0x0e //器件地址設定

#define Reserverd1Addr 0x0f //保留

#define Reserverd2Addr 0x19 //保留

#define ID1Addr 0x1c //ID地址1

#define ID2Addr 0x1d //ID地址2

#define ID3Addr 0x1e //ID地址3

#define ID4Addr 0x1f //ID地址4


//************函數聲明*****************************************************

void start(); //MLX90614發起始位子程序

void stop(); //MLX90614發結束位子程序

uchar ReadByte(void); //MLX90614接收位元組子程序

void send_bit(void); //MLX90614發送位子程序

void SendByte(uchar number); //MLX90614接收位元組子程序

void read_bit(void); //MLX90614接收位子程序

void delay(uint N); //延時程序

uint readtemp(void); //讀溫度數據

void init1602(void); //LCD初始化子程序

void busy(void); //LCD判斷忙子程序

void cmd_wrt(uchar cmd); //LCD寫命令子程序

void dat_wrt(uchar dat); //LCD寫數據子程序

void display(uint Tem); //顯示子程序

void Print(uchar *str); //字元串顯示程序


//*************主函數*******************************************

void main()

{

uint Tem; //溫度變數

SCK=1;

SDA=1;

delay(4);

SCK=0;

delay(1000);

SCK=1;

init1602(); //初始化LCD

while(1)

{

Tem=readtemp(); //讀取溫度

cmd_wrt(0x01); //清屏

Print(" Temperature: "); //顯示字元串 Temperature: 且換行

display(Tem); //顯示溫度

Print(" ^C"); //顯示攝氏度

delay(10000); //延時再讀取溫度顯示

}

}

void Print(uchar *str) //字元串顯示程序

{

while(*str!='') //直到字元串結束

{

dat_wrt(*str); //轉成ASCII碼

str++; //指向下一個字元

}

}


//*********輸入轉換並顯示*********

void display(uint Tem)

{

uint T,a,b;

T=Tem*2;

if(T>=27315) //溫度為正

{

T=T-27315; //

a=T/100; //溫度整數

b=T-a*100; //溫度小數

if(a>=100) //溫度超過100度

{

dat_wrt(0x30+a/100); //顯示溫度百位

dat_wrt(0x30+a%100/10); //顯示溫度十位

dat_wrt(0x30+a%10); //顯示溫度個位

}

else if(a>=10) //溫度超過10度

{

dat_wrt(0x30+a%100/10); //顯示溫度十位

dat_wrt(0x30+a%10); //顯示溫度個位

}

else //溫度不超過10度

{

dat_wrt(0x30+a); //顯示溫度個位

}

dat_wrt(0x2e); //顯示小數點

if(b>=10) //溫度小數點後第1位數不等於0

{

dat_wrt(0x30+b/10); //顯示溫度小數點後第1位數

dat_wrt(0x30+b%10); //顯示溫度小數點後第2位數

}

else //溫度小數點後第1位數等於0

{

dat_wrt(0x30); //顯示溫度小數點後第1位數0

dat_wrt(0x30+b); //顯示溫度小數點後第2位數

}

}

else //溫度為負

{

T=27315-T;

a=T/100;

b=T-a*100;

dat_wrt(0x2d); //顯示負號

if(a>=10) //溫度低於負10度

{

dat_wrt(0x30+a/10); //顯示溫度十位

dat_wrt(0x30+a%10); //顯示溫度個位

}

else //溫度高於負10度

{

dat_wrt(0x30+a); //顯示溫度個位

}

dat_wrt(0x2e); //顯示小數點

if(b>=10) //溫度小數點後第1位數不等於0

{

dat_wrt(0x30+b/10); //顯示溫度小數點後第1位數

dat_wrt(0x30+b%10); //顯示溫度小數點後第2位數

}

else //溫度小數點後第1位數等於0

{

dat_wrt(0x30); //顯示溫度小數點後第1位數0

dat_wrt(0x30+b); //顯示溫度小數點後第2位數

}

}

}

//************************************

void start(void) //停止條件是 SCK=1時,SDA由1到0

{

SDA=1;

delay(4);

SCK=1;

delay(4);

SDA=0;

delay(4);

SCK=0;

delay(4);

}

//------------------------------

void stop(void) //停止條件是 SCK=1時,SDA由0到1

{

SCK=0;

delay(4);

SDA=0;

delay(4);

SCK=1;

delay(4);

SDA=1;

}

//---------發送一個位元組---------

void SendByte(uchar number)

{

uchar i,n,dat;

n=Nack_number; //可以重發次數

Send_again:

dat=number;

for(i=0;i<8;i++) //8位依次發送

{

if(dat&0x80) //取最高位

{

bit_out=1; //發1

}

else

{

bit_out=0; //發0

}

send_bit(); //發送一個位

dat=dat<<1; //左移一位

}

read_bit(); //接收1位 應答信號

if(bit_in==1) //無應答時重發

{

stop();

if(n!=0)

{

n--; //可以重發Nack_number=10次

goto Repeat; //重發

}

else

{

goto exit; //退出

}

}

else

{

goto exit;

}

Repeat:

start(); //重新開始

goto Send_again; //重發

exit: ; //退出

}

//-----------發送一個位---------

void send_bit(void)

{

if(bit_out==1)

{

SDA=1; //發1

}

else

{

SDA=0; //發0

}

_nop_();

SCK=1; //上升沿

delay(4);delay(4);

SCK=0;

delay(4);delay(4);

}

//----------接收一個位元組--------

uchar ReadByte(void)

{

uchar i,dat;

dat=0; //初值為0

for(i=0;i<8;i++)

{

dat=dat<<1; //左移

read_bit(); //接收一位

if(bit_in==1)

{

dat=dat+1; //為1時對應位加1

}

}

SDA=0; //發送應答信號0

send_bit();

return dat; //帶回接收數據

}

//----------接收一個位----------

void read_bit(void)

{

SDA=1; //數據端先置1

bit_in=1;

SCK=1; //上升沿

delay(4);delay(4);

bit_in=SDA; //讀數據

_nop_();

SCK=0;

delay(4);delay(4);

}



//------------------------------

uint readtemp(void)

{

SCK=0;

start(); //開始條件

SendByte(0x00); //發送從地址00

SendByte(0x07); //發送命令

start(); //開始條件

SendByte(0x01); //讀從地址00

bit_out=0;

tempL=ReadByte(); //讀數據低位元組

bit_out=0;

tempH=ReadByte(); //讀數據高位元組

bit_out=1;

err=ReadByte(); //讀錯誤信息碼

stop(); //停止條件

return(tempH*256+tempL);

}

//******************LCD顯示子函數***********************

void init1602(void) //初始化LCD

{

cmd_wrt(0x01); //清屏

cmd_wrt(0x0c); //開顯示,不顯示游標,不閃爍

cmd_wrt(0x06); //完成一個字元碼傳送後,游標左移,顯示不發生移位

cmd_wrt(0x38); //16×2顯示,5×7點陣,8位數據介面

}

void busy(void) //LCD忙標志判斷

{

flag=0x80; //賦初值 高位為1 禁止

while(flag&0x80) //讀寫操作使能位禁止時等待 繼續檢測

{

P0=0xff;

RS=0; //指向地址計數器

RW=1; //讀

LCDE=1; //信號下降沿有效

flag=P0; //讀狀態位 高位為狀態

LCDE=0;

}

}

void cmd_wrt(uchar cmd) //寫命令子函數

{

LCDE=0;

busy(); //檢測 讀寫操作使能嗎

P0=cmd; //命令

RS=0; //指向命令計數器

RW=0; //寫

LCDE=1; //高電平有效

LCDE=0;

}

void dat_wrt(uchar dat) //寫數據子函數

{

busy(); //檢測 讀寫操作使能嗎

LCDE=0;

if(flag==16)

{

RS=0; //指向指令寄存器

RW=0; //寫

P0=0XC0; //指向第二行

LCDE=1; //高電平有效

LCDE=0;

}

RS=1; //指向數據寄存器

RW=0; //寫

P0=dat; //寫數據

LCDE=1; //高電平有效

LCDE=0;

}

//------------延時--------------

void delay(uint n)

{

uint j;

for(j=0;j<n;j++)

{

_nop_();

}

}


『伍』 51單片機怎麼寫編碼器的程序

可以用T0或T1的計數器模式來處理編碼器的脈沖信號。

『陸』 51單片機開發板和絕對式編碼器連接測量角度的程序

#include <reg52.h>
#include "inc/delay.h"
#include "inc/hc595.h"

#define uchar unsigned char
#define uint unsigned int
sbit PIN_ROTARY_A = P2^0; //引腳1介面
sbit PIN_ROTARY_B = P2^1; //引腳2介面
sbit PIN_ROTARY_C = P2^2; //按下的介面

sbit PIN_ROTARY_D = P2^3; //按下的介面

//uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
/* 存儲待發送的數據 */
/* 1->8的段碼表 */
code unsigned char ucDis_Segmentcode[16] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/* 位碼表 */
code unsigned char ucDis_Bitcode[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
uchar dis_XS[8] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d};
uchar count = 0;
uchar flag;
uchar Last_BMB_status;

uchar Current_BMB_status;

void display()
{
uchar i;

dis_XS[0] = ucDis_Segmentcode[count/100]; //百位

dis_XS[1] = ucDis_Segmentcode[count%100/10]; //十位

dis_XS[2] = ucDis_Segmentcode[count%10]; //個位

if(i < 2)
{
i++;
}
else
{
i = 0;
}

// for (i = 0; i < 3; i++ )
{
Send_Data(dis_XS[i], ucDis_Bitcode[i]);
//PIN_ROTARY_D = 0;
// Delay1ms(1);
}
}

//************************************************
void main()
{

TMOD=0x01; //定時器0,工作方式1
TH0=0xD8;
TL0=0xF0; //給定時器裝上初值,10ms中斷一次
ET0=1; //打開定時器中斷
EA =1; //打開總中斷
TR0=1; //啟動定時器0

while(1)
{
//display();
Last_BMB_status=PIN_ROTARY_B;

while(!PIN_ROTARY_A) //BMA為低電平時
{
Current_BMB_status = PIN_ROTARY_B;
flag = 1; //標志位置為1說明編碼開關被旋轉了
}

if(flag == 1)
{
flag = 0; //時刻要注意這一點!給標志位清零
if((Last_BMB_status == 0)&&(Current_BMB_status == 1)) //BMB上升沿表示正轉
{
count++;
if(count == 255)
{
count = 0;
}
}
if((Last_BMB_status == 1)&&(Current_BMB_status == 0)) //BMB下降沿表示反轉
{
count--;
if(count == 0)
{
count = 255;
}
}
}
}
}

//***********************************************
void timer0() interrupt 1//定時器0的中斷服務程序
{
TH0=0xF8; // TH0=0xD8;
TL0=0xF0; //再次裝入初值
display(); //每隔10ms顯示一次
if(!PIN_ROTARY_C) //按下旋轉編碼開關則計數清零
{
count = 0;
}
PIN_ROTARY_D = !PIN_ROTARY_D;
}

『柒』 用51單片機編程

單片機中只有一條語句是對進制調整的
DA A 對累加器A的結果進行十進制調整
如果隨意對一個累加器A中的二進制數據進行「二進制轉十進制」調整是沒有任何實際意義的!

DA調整的對象是ADD或ADDC以後的結果,而且是BCD碼相加以後才能夠加以調整,否則沒有實際意義!

比如,現在我想執行12D+39D也就是兩個十進制數相加這樣一個加法(有時候程序處理的需要,數據在單片機中是以BCD碼的形式存儲的,也就是12H和39H(十六進制),但我們可以人為將它們看為12D和39D(十進制),而且還希望相加以後的結果為51H,也就是說符合十進制運算規則12+39=51,而不是4BH的結果),但這樣的十進制加法運算在單片機中是不能夠直接實現的。因為單片機只能夠執行二進制加法指令,也就是所有的運算都按照二進制中的規則進行!

於是就出現了DA調整指令!

現在12H+39H,將12H放於A中,執行 ADD A,#39H指令,則結果為4BH,這不是我們希望的51H的數據形式!!這時執行DA A 指令後,就會將A中的數據調整為51H(具體調整過程和原理你可以詳細看書,如果單片機書中講的不詳細,那麼微機原理中一定說的非常詳細),而我們按照BCD碼規則就將其看為51D,符合我們的要求!

也就是說加數和被加數都是BCD碼的形式,最大也只可能是99H,也就是我們十進制數中的99,只有這樣才會有實際的意義!
所以DA A指令只用於十進制BCD碼加法指令以後,否則是沒有實際意義的!
在單片機中數據就是以二進制存放的也可以說是以16進制存放(4位二進制就是16進制),所以一般來說在單片機只有二進制轉十進制才有意義,通過單片機將十進制轉二進制是沒意義的。 這個一般都是我們自己把一個十進制數轉成二進制再送給單片機處理。
非得編寫程序的話 程序如下
----------------------------------------------------------------------
;二進制整數(2位)轉換為十進制整數(組合BCD碼)
;入口: R3,R4
;出口: R0
IBTD22 : MOV A,R0
PUSH A
MOV R7,#03H
CLR A
IBD221 : MOV @R0,A
INC R0
DJNZ R7,IBD221
POP A
MOV R0,A
MOV R7,#10H
IBD222 : PUSH A
CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV B,#03H
IBD223 : MOV A,@R0
ADDC A,@R0
DA A
MOV @R0,A
INC R0
DJNZ B,IBD223
POP A
MOV R0,A
DJNZ
--------------------------------------------------
;二進制整數(M位)轉換為十進制整數(組合BCD碼)
;入口: R1,M,N
;出口: R0
IBTDMN : MOV A,R0
MOV R2,A
MOV A,R1
MOV R3,A
MOV B,N
CLR A
IBDMN1 : MOV @R0,A
INC R0
DJNZ B,IBDMN1
MOV A,M
SWAP A
RR A
CLR C
MOV R7,A
IBDMN2 : MOV A,R2
MOV R0,A
MOV A,R3
MOV R1,A
MOV B,M
IBDMN3 : MOV A,@R1
RLC A
MOV @R1,A
INC R1
DJNZ B,IBDMN3
MOV B,N
IBDMN4 : MOV A,@R0
ADDC A,@R0
DA A
JNB ACC.4,IBDMN5
SETB C
CLR ACC.4
IBDMN5 : MOV @R0,A
INC R0
DJNZ B,IBDMN4
DJNZ R7,IBDMN2
MOV A,R2
MOV R0,A
RET
----------------------------------------------------------------
BCD整數轉換為二進制整數(1位)
;入口: R0(高位地址),R7
;出口: R4
IDTB1: CLR A
MOV R4,A
IDB11: MOV A,R4
MOV B,#0AH
MUL AB
ADD A,@R0
INC R0
MOV R4,A
DJNZ R7,IDB11
RET
------------------------------------------
;BCD整數轉換為二進制整數(N位)
;入口: R1(高位地址),M,N
;出口: R0
IDTBMN : MOV A,R0
MOV R2,A
MOV B,N
CLR A
IDBMN1 : MOV @R0,A
INC R0
DJNZ B,IDBMN1
MOV A,R2
MOV R0,A
MOV A,M
MOV NCNT,A
IDBMN2 : MOV R7,N
CLR A
CLR F0
IDBMN3 : XCH A,@R0
MOV B,#0AH
MUL AB
MOV C,F0
ADDC A,@R0
MOV F0,C
MOV @R0,A
INC R0
MOV A,B
DJNZ R7,IDBMN3
MOV A,R2
MOV R0,A
MOV A,@R1
INC R1
ADD A,@R0
MOV @R0,A
DJNZ NCNT,IDBMN2
RET
----------------------------------------------------------
NDIV31 : MOV A,R2
MOV B,R7
DIV AB
PUSH A
MOV R2,B
MOV B,#10H
NDV311 : CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV F0,C
CLR C
SUBB A,R7
JB F0,NDV312
JC NDV313
NDV312 : MOV R2,A
INC R4
NDV313 : DJNZ B,NDV311
POP A
CLR OV
JZ NDV314
SETB OV
NDV314 : XCH A,R2
MOV R7,A
RET

『捌』 51單片機ec11編碼器中斷法

配置一個1ms定時器,並設置為自動清零模式,配置好後記得打開定時器中斷。首先要開啟定時器TIM3,我們使用這個 HAL_TIM_IC_Start_IT(htim, Channel);啟動定時器。
使用定時器回調函數
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
在裡面編寫上面的程序,因為我們將B相接在PA7引腳,所以我們使用switch case語句進行判斷引腳電平,如果單片機檢測到A相為高電平就會進入這個中斷判斷B相電平,低電平為反轉,高電平極為正轉(程序中的cnt為計數作用)。

『玖』 51單片機檢測增量式旋轉光電編碼器匯編程序有點問題,請高手看看,分數不是問題

不明白你寫的,你把題目說的清晰一點 ,看了好幾遍,程序編的挺簡單

閱讀全文

與51單片機編碼器程序相關的資料

熱點內容
解壓小游戲測試鑽石劍的硬度 瀏覽:962
java結束函數 瀏覽:622
打開遠程桌面的命令 瀏覽:836
樹莓派如何搭建mqtt伺服器 瀏覽:587
怎麼加密w8文件 瀏覽:609
linuxprogram 瀏覽:708
php介面編程思想 瀏覽:92
如何下載電話軟體app 瀏覽:906
java命令行解析 瀏覽:572
雲伺服器白嫖 瀏覽:917
程序員小清新 瀏覽:989
編譯器地址8位元組對齊 瀏覽:464
三菱plc編程win1064 瀏覽:258
高中英語單詞pdf 瀏覽:425
編譯原理詞法分析常見問題 瀏覽:197
車小藝app怎麼更新 瀏覽:77
手機app被管控如何移除 瀏覽:753
51單片機溫濕度檢測 瀏覽:575
安卓抖音顯示沒網路是怎麼回事 瀏覽:819
2d我的世界源碼 瀏覽:620