软件:
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、
PPM的编码:
如图、利用单片机的PWM功能产生PWM1和PWM2连个脉冲。
利用数字电路合成PPM脉冲。
可以看出当PWM1的占空比是0时,PPM如下图的A,
PWM1的占空比是1时,PPM如下图的B,
PPM的合成:
如第一个图可知,PPM可以将PPM1求反后和PWM2相与得到。
故设计如上发送模块。接收模块结果波形整形送到单片机处理。
PPM发送的数据(16位的双字节数)。
定义占空比一定的脉冲为发送的数据。
发送0, 0, 0, 0-3, 4-7, 8-11, 12-15
前面是头,可以提供接收PPM的单个周期。
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
#include
#include
#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;
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』