幫一個畢業生做的《PIC16F877A基于PPM的激光通信》仿真。
軟件:
MPLAB X IDE v4.15編譯 proteus 8.6仿真.
1、仿真電路圖;
2、發送和接收源程序加注釋。
請看注釋。
原理:
1)ADC讀取并用led顯示ADC讀數,并通過usart進行輸出。
2)通過PPM原理進行通訊傳輸到另外一個單片機,LED顯示接收的值。
具體請看附件
希望大家頂一下。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
圖片.jpg (247.76 KB, 下載次數: 158)
下載附件
原理和仿真
2018-6-14 15:54 上傳
1、發送模塊:讀取ADC數值,LED顯示10位ADC值。并通過PPM發送。
2、接收模塊:PPM接收到的數據。LED顯示接收的ADC值(10bits)
基于PIC單片機的PPM調制激光通信收發器 PPM (pulse position modulation) 脈沖位置調制。 如圖1、 如圖、利用單片機的PWM功能產生PWM1和PWM2連個脈沖。 利用數字電路合成PPM脈沖。 可以看出當PWM1的占空比是0時,PPM如下圖的A, PWM1的占空比是1時,PPM如下圖的B,
如第一個圖可知,PPM可以將PPM1求反后和PWM2相與得到。 故設計如上發送模塊。接收模塊結果波形整形送到單片機處理。 定義占空比一定的脈沖為發送的數據。 發送0, 0, 0, 0-3, 4-7, 8-11, 12-15 前面是頭,可以提供接收PPM的單個周期。 PPM接收到的數據是: 由圖中知道 (3-2)即3測量的寬度減去波形的周期的等于0-3對應的PWM脈寬1 (4+脈寬1-2)即4測量的寬度加上脈寬1減去波形的周期的等于4-7對應的PWM脈寬2 (5+脈寬2-2)即5測量的寬度加上脈寬2減去波形的周期的等于8-11對應的PWM脈寬3 (6+脈寬3-2)即6測量的寬度加上脈寬3減去波形的周期的等于12-15對應的PWM脈寬4 在將四個半字節數合成2個字節16位的值。
單片機源程序如下:
- #include "sys.h"
- #include <stdint.h> /* For uint8_t definition */
- #include <stdbool.h> /* For true/false definition */
- #include <stdio.h>
- #define AKING PORTCbits.RC0
- const uint8_t uart_disp1[]={"ADC result(DEC) is:"}; //uart DISP
- void usart_send_8bits(uint8_t send_data);
- void ppm_send_unit(uint8_t send_data);
- void time1_init();
- uint16_t adc_read()
- {
- ADCON1=0x80; //fosc/2,A口都是AD口,Vref=VDD
- ADCON0=0x01; //AN0進行轉換,允許轉換
- //ADFM ADCS2 -- -- PCFG3 PCFG2 PCFG1 PCFG0
- // 1 0 0 0 0 0
- //ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE -- ADON
- // 0 0 0 0 0 0 1
- __delay_ms(2); //delay
- GO=0x01; //開始AD轉換
- while(GO); //是否轉換完畢,GO=0轉換完畢
- uint16_t adc_result=(uint16_t)ADRESH<<8 |ADRESL; //轉換結果,10bits
- return adc_result; //return ADC results
- }
- void sys_init() //SYS INIT
- {
- TRISC=0; //PORTC is output
- PORTC=0; //Clear PORTC
- TRISD=0; //PORTD is output
- PORTD=0; //Clear PORTD
- }
- void uart_init() //UART INIT
- {
- TXSTA =0x24; //TXEN=1,TX enable
- //BRGH=1,high speed baud
- RCSTA =0b10010000; //SPEN=1,receive enable
- //CREN=1
- TRISB=0x00; //PORTB is output
- SPBRG=103; //SPBRG=FOSC/(16*baud)-1; (high speed baud)
- // =16000000/(16*9600)-1
- // =104-1=103
- INTCON=0; //no interrupt
- PIE1=0; //PIE1 disable
- PIE2=0; //PIE2 disable
- PIR1=0; //Clear PIR1(flag of interrupt)
- PIR2=0; //Clear PIR2(flag of interrupt)
- }
- void usart_send_16bits(uint16_t send_data) //send 2 bytes
- {
- uint16_t send_buffer;
- send_buffer=send_data;
- usart_send_8bits((uint8_t)(send_buffer>>8)); //send high byte
- usart_send_8bits((uint8_t)(send_data)); //send low byte
- }
- void usart_send_8bits(uint8_t send_data) //send one bytes
- {
- TXREG=(uint8_t)(send_data);
- while(TRMT==0); //send is over
- }
- void TMR1_init() //TMR1 INIT
- {
- T1CON=0; //TMR1 is TIMR
- TMR1=(uint16_t)(65535-985); //delay is 1000*FOSC=1000*0.25=250us
- TMR1IF=0; //Clear TMR1IF
- }
- void PWM_init() //PWM INIT
- {
- PR2=0xff; //寫入PR2寄存器設置PWM周期,PWM周期=[(PR2)+1]*4*TOSC*(TMR2預分頻比)
- // =[255+1]*4*4/16=256us
- CCPR1L=0; //Clear CCPR1L
- T2CON=0x01; //TMR2預分頻比=1:4
- CCP1CON=0; //Clear CCP1CON
- CCP2CON=0; //Clear CCP2CON
- TMR2ON=1; //TMR2 enable
- }
- void PPM_unit(uint8_t send_data) //PPM send half byte
- {
- TMR1_init(); //TMR1 delay 250us
- TMR1ON=1; //TMR1 enable
- TMR2=0xF0; //to start PWM
- CCPR1L=(uint8_t)(send_data<<3); //CCPR1L
- CCPR2L=(uint8_t)(CCPR1L+8); //CCPR2L=CCPR1L+8
- CCP1CON=0x0c; //CCP1 PWM enable
- CCP2CON=0x0c; //CCP2 PWM enable
- while(TMR1IF==0); //250us delay is over
- TMR1IF=0; //clear TMR1IF
- CCP1CON=0x0; //CCP1 PWM disable
- CCP2CON=0x0; //CCP2 PWM disable
-
- }
- void PPM_send(uint16_t send_data) //PPM send 2 byte
- {
- uint8_t send_buffer[7];
- send_buffer[3]=(uint8_t)send_data; //half byte
- send_buffer[4]=(uint8_t)send_data; //half byte
- send_buffer[5]=(uint8_t)(send_data>>8); //half byte
- send_buffer[6]=(uint8_t)(send_data>>8); //half byte
- send_buffer[0]=0; //head
- send_buffer[1]=0; //head
- send_buffer[2]=0; //head
- send_buffer[3]=(uint8_t)(send_buffer[3] & 0x0f); //half byte
- send_buffer[4]=(uint8_t)(send_buffer[4]>>4); //half byte
- send_buffer[5]=(uint8_t)(send_buffer[5] & 0x0f); //half byte
- send_buffer[6]=(uint8_t)(send_buffer[6]>>4); //half byte
- for(uint8_t i=0;i<7;i++)
- {
- PPM_unit(send_buffer[i]); //PPM send head(0,0,0) & half byte,half byte,half byte,half byte 7 bytes
- }
- }
- void UART_disp(uint16_t uart_data) //UART DISP
- {
- for(uint8_t i=0;i<19;i++)
- {
- usart_send_8bits(uart_disp1[i]); //PRINT"ADC result(DEC) is:"
- }
- uint8_t buff[4];
- sprintf(buff,"%d",uart_data); //ADC result Dec
- for(uint8_t i=0;i<4;i++)
- {
- usart_send_8bits(buff[i]); //
- }
- usart_send_8bits(0x0d); //send "enter"
- }
- void main(void)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (57.51 KB, 下載次數: 141)
下載附件
2018-6-14 16:56 上傳
所有資料51hei提供下載:
sendrece2.rar
(499.06 KB, 下載次數: 90)
2018-6-14 15:55 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|