帮一个毕业生做的《PIC16F877A基于PPM的激光通信》仿真。
软件:
MPLAB X IDE v4.15编译 proteus 8.6仿真.
1、仿真电路图;
2、发送和接收源程序加注释。
请看注释。
原理:
1)ADC读取并用led显示ADC读数,并通过usart进行输出。
2)通过PPM原理进行通讯传输到另外一个单片机,LED显示接收的值。
具体请看附件
希望大家顶一下。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
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黑下载附件…………
复制代码
所有资料51hei提供下载:
sendrece2.rar
(499.06 KB, 下载次数: 90)
|