Here is a summary of the 315M wireless module’s reception program.
#include <AT89X52.H>
#include "string.h"
// LCD Block
#define LCM_RW P3_6 // Define pin
#define LCM_RS P3_5
#define LCM_E P3_7
#define LCM_Data P1
#define Busy 0x80 // Used to detect Busy flag in LCM status word
typedef int byte;
typedef unsigned int word;
void Read_Temp(void);
void mychar(char,char);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void delay(word useconds)
{
for(;useconds>0;useconds--);
}
void mychar(char xx,char yy)
{
DisplayOneChar(0,0,0x54);
DisplayOneChar(1,0,0x65);
DisplayOneChar(2,0,0x6D);
DisplayOneChar(3,0,0x70);
DisplayOneChar(4,0,0x65);
DisplayOneChar(5,0,0x72);
DisplayOneChar(6,0,0x61);
DisplayOneChar(7,0,0x74);
DisplayOneChar(8,0,0x75);
DisplayOneChar(9,0,0x72);
DisplayOneChar(10,0,0x65);
DisplayOneChar(11,0,0x3A);
/////////////////////// Custom Character
WriteCommandLCM(0x48, 0); // First line
WriteDataLCM(0x06);
WriteCommandLCM(0x49, 0); // Second line
WriteDataLCM(0x09);
WriteCommandLCM(0x4a, 0); // Third
WriteDataLCM(0x09);
WriteCommandLCM(0x4b, 0); // Fourth
WriteDataLCM(0x06);
WriteCommandLCM(0x4c, 0); // Fifth
WriteDataLCM(0x00);
WriteCommandLCM(0x4d, 0); // Sixth
WriteDataLCM(0x00);
WriteCommandLCM(0x4e, 0); // Seventh
WriteDataLCM(0x00);
WriteCommandLCM(0x4f, 0); // Eighth
WriteDataLCM(0x00);
DisplayOneChar(xx,yy,0x01);
DisplayOneChar(xx+1,yy,0x43);
}
// Write data
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); // Check busy
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; // If the crystal oscillator speed is too high, a small delay can be added here
LCM_E = 0; // Delay
LCM_E = 1;
}
// Write command
void WriteCommandLCM(unsigned char WCLCM,BuysC) // BuysC is ignored when 0
{
if (BuysC) ReadStatusLCM(); // Check busy as needed
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
// Read status
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); // Check busy signal
return(LCM_Data);
}
void LCMInit(void) // LCM Initialization
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); // Three times display mode setting, do not check busy signal
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); // Display mode setting, start requiring busy signal check
WriteCommandLCM(0x08,1); // Turn off display
WriteCommandLCM(0x01,1); // Clear display
WriteCommandLCM(0x06,1); // Set cursor movement
WriteCommandLCM(0x0C,1); // Display on and cursor settings
}
// Display a character at specified position
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; // Limit X to not exceed 15, Y cannot exceed 1
if (Y) X |= 0x40; // When displaying the second line, address code +0x40;
X |= 0x80; // Calculate instruction code
WriteCommandLCM(X, 0); // Do not check busy signal here, send address code
WriteDataLCM(DData);
}
// Display a string of characters at specified position *** The original does not display when encountering space 0x20 ***
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength,j;
ListLength = strlen(DData);
Y &= 0x1;
X &= 0xF; // Limit X to not exceed 15, Y cannot exceed 1
if (X <= 0xF) // X coordinate should be less than 0xF
{
for(j=0;j<ListLength;j++)
{
DisplayOneChar(X, Y, DData[j]); // Display single character
X++;
}
}
}
// 5ms delay
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
// 400ms delay
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
sbit W_IN = P2^1;
sbit W_OUT = P2^0;
unsigned char w_data; // Used to store duration between two rising edges during reception, store the first half during sending
unsigned char send_busy = 0;// Store second half during sending
unsigned char recv_TImer = 0;
bit w_stat, last_w_stat;
unsigned char jiffies=0;
void clock_TImer(void) interrupt 1 using 1{
if (send_busy){
if(w_data){
w_data--;
w_stat = 0;
}else{
send_busy--;
w_stat = 1;
}
W_OUT = w_stat;
}else{
w_stat = W_IN;
if (w_stat != last_w_stat){
last_w_stat = w_stat;
if (w_stat){
w_data = recv_TImer;
recv_TImer = 0;
}
}
if (~recv_timer)//if(recv_busy != 0xff)
recv_timer++;
}
jiffies++;
}
void clock_init(void){
jiffies = 0;
TMOD=0x02;
TH0=TL0=0x0ce;//12M,50us
// TH0=TL0=0x7a;//16M
// TH0=TL0=0x75;//16.59M
// TH0=TL0=0x72;//17M
// TH0=TL0=0x37;//24M
// TH0=TL0=0x47;//22.1844M, 100us
// TH0=TL0=0xa3;//22.1844M, 50us
EA=1;
ET0=1;
TR0=1;
}
void init_serialcomm(void)
{
SCON = 0x50; // SCON: serial mode 1, 8-bit UART, enable ucv
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit reload
PCON |= 0x80; // SMOD=1;
TH1 = 0x0e6; // Baud:2400 fosc=11.0592MHz :f4
TL1 = 0x0e6;
// IE |= 0x90; // Enable Serial Interrupt
TR1 = 1; // timer 1 run
RI=0;
TI=1;
}
void serial_out(unsigned char d){
while(!TI);
TI=0;
SBUF=(d);
}
void send_string_com(unsigned char *str,int strlen)// Serial program
{ unsigned char sum;
unsigned char k=0;
do
{
// sum^=*(str+k);
serial_out(*(str + k));
// serial_out('a');
k++;
} while(k < strlen);
// serial_out(sum);
// serial_out('e');
}
// Wait for specified length of serial data to arrive, timeout value is the interval time between every two bytes rather than waiting for the entire string's time.
// Timeout unit is time_out * 100uS
bit wait_serial(unsigned char *p, unsigned char len, unsigned char time_out){
unsigned int time=jiffies;
unsigned char n=0;
do{
if (RI){
p[n++]=SBUF;
RI=0;
if(n==len)
return 0;
time=jiffies;
}
}while(jiffies-time < time_out);
return 1;
}
sys_init(){
clock_init();
init_serialcomm();
}
//=============================================================// Send program starts//=============================================================#define PULS_0_WIDTH 8 // Low level pulse width
#define PULS_1_WIDTH 16 // High level pulse width
#define PULS_HEAD_WIDTH 8 // Leading signal pulse width
#define PULS_START_WIDTH 24 // Guide signal pulse width
#define PULS_STOP_WIDTH 8 // End code pulse width
#define PULS_HEAD_COUNTS 16 // Leading signal length
unsigned char send_buf[16];
#define send_byts send_buf[0] // Remaining bytes, 0 after sending
unsigned char sending_byte; // Currently sending byte
unsigned char send_byte_p; // Number of bytes sent (including currently sending byte)
unsigned char send_bit_p; // Number of bits sent in the currently sending byte (including currently sending bit)
#define SEND_PROGRESSING 0x41
#define SEND_FAILED 0x21
#define SEND_SUCCESS 0x31
unsigned char send_stat = 0; // Current status of sending program, 0 when normal
unsigned char head_counts; // Leading signal counter (including guide signal)
void start_send(){
send_byte_p = 0;
send_bit_p = 0;
send_stat = SEND_PROGRESSING;
head_counts = 16;
}
#define START_SEND(byts) send_buf[0]=byts;send_byts=byts;start_send()
// Before sending, clear send_byte_p, send_bit_p, send_stat, and set send_byts
// During sending, the remaining number of bytes can be obtained from send_byts, and the number of bytes sent can be obtained from send_byte_p. Note that the currently sending byte is considered as sent.
// During sending, the sending status can be obtained from send_stat.
// After sending is complete, both send_byts and send_bit_p will be 0.
#define SEND_PULS(x) w_data=send_busy=(x>>1)
void send(){
// The following two lines have already been executed in wirless(), so there is no need to write them again
// if (send_stat != SEND_PROGRESSING)
// return;
if (!send_busy){
if(send_byts || send_bit_p){
if (head_counts){
head_counts--;
if(head_counts)
SEND_PULS(PULS_HEAD_WIDTH);
else
SEND_PULS(PULS_START_WIDTH);
}else{
if (send_bit_p == 0){
sending_byte = send_buf[send_byte_p];
send_byte_p++;
send_byts--;
send_bit_p = 8;
}
if(sending_byte & 0x80){
SEND_PULS(PULS_1_WIDTH);
}else{
SEND_PULS(PULS_0_WIDTH);
}
sending_byte <<= 1;
send_bit_p--;
}
}else{
SEND_PULS(PULS_STOP_WIDTH);
send_stat = SEND_SUCCESS;
}
}
return;
}
//=============================================================// Send program ends//=============================================================//=============================================================// Reception program starts//=============================================================unsigned char recv_buf[16];
#define recv_byts recv_buf[0] // Number of bytes to be received, specified by the first byte of each packet
unsigned char recving_byte; // Currently receiving byte
unsigned char recv_byte_p; // Number of bytes received (excluding currently receiving byte)
unsigned char recv_bit_p; // Number of bits waiting to be received in the currently receiving byte (excluding currently receiving)
#define RECV_FAILED 0x31
#define RECV_SUCCESS 0x41
unsigned char recv_stat = 0; // Current status of receiving program, 0 when normal
unsigned char recv_step = 0; // Leading pulse flag, 0 when waiting for leading, 1 when waiting for data
#define TEST_PULS(puls_in, puls_type) (puls_in > puls_type - PULS_0_WIDTH / 2 && puls_in < puls_type + PULS_0_WIDTH / 2)
#define HEAD_NEED_RECIVED 8
void recv(){
unsigned puls_width;
if ((recv_stat == RECV_SUCCESS) || !w_data)
return;
puls_width = w_data;
w_data = 0;
#if 0 // Output pulse width
serial_out(puls_width);
// printhex(puls_width);
#endif
if (recv_step < HEAD_NEED_RECIVED){
if(TEST_PULS(puls_width, PULS_HEAD_WIDTH)){
recv_step++;
}else{
recv_step = 0;
}
}else if (recv_step == HEAD_NEED_RECIVED){
if(TEST_PULS(puls_width, PULS_START_WIDTH)){
serial_out(0xbb);
recv_byte_p = 0;
recv_bit_p = 8;
recv_stat = 0;
recv_step++;
}else{
if(!TEST_PULS(puls_width, PULS_HEAD_WIDTH)){
recv_step = 0;
}
}
}else{
//serial_out(puls_width);
recving_byte <<= 1;
if(TEST_PULS(puls_width, PULS_0_WIDTH)){
recving_byte &= 0xfe;
}else if(TEST_PULS(puls_width, PULS_1_WIDTH)){
recving_byte |= 1;
}else{
serial_out(puls_width);
recv_step = 0;
serial_out(0xaa);
return;
}
recv_bit_p--;
if(recv_bit_p == 0){ // Finished receiving one byte
recv_bit_p = 8;
// serial_out(recving_byte); // Output received character
recv_buf[recv_byte_p] = recving_byte;
recv_byte_p++;
if(recv_byte_p == recv_byts){
recv_step = 0;
recv_stat = RECV_SUCCESS;
}
}
}
}
//=============================================================// Reception program ends//=============================================================#define SEND_DELAY_TIME 20 // Collision delay (unit: milliseconds)
unsigned char send_delay = SEND_DELAY_TIME;
#define VALID_PULS_COUNT 10
unsigned char valid_puls_counts = VALID_PULS_COUNT;
// Collision detection is implemented in this function. Due to the limitations of the wireless module itself, collision detection is not complete, only before sending
// Check whether other units are using the channel, collision interference during sending cannot be detected. Tested, the effect is acceptable
void wirless(){
if (send_stat == SEND_PROGRESSING && send_delay == 0){
send();
if (send_stat == SEND_SUCCESS)
send_delay = SEND_DELAY_TIME;
}else{
recv();
if (recv_step > HEAD_NEED_RECIVED) // If it detects that another unit is currently sending, continue waiting
send_delay = SEND_DELAY_TIME;
else{
if(TEST_PULS(w_data, PULS_0_WIDTH) // If it detects that another unit is currently sending, continue waiting
|| TEST_PULS(w_data, PULS_1_WIDTH)
//|| TEST_PULS(w_data, PULS_HEAD_WIDTH)
|| TEST_PULS(w_data, PULS_START_WIDTH)
//|| TEST_PULS(w_data, PULS_STOP_WIDTH)
){
if (valid_puls_counts)
valid_puls_counts--;
else
send_delay = SEND_DELAY_TIME;
}else{
valid_puls_counts = VALID_PULS_COUNT;
}
}
}
}
void Display_T()
{
DisplayOneChar(9,1,recv_buf[5]);
DisplayOneChar(8,1,recv_buf[4]);
DisplayOneChar(7,1,recv_buf[3]);
DisplayOneChar(6,1,recv_buf[2]);
DisplayOneChar(5,1,recv_buf[1]);
DisplayOneChar(0,0,0x54);
}
#define SCMD_SET_PORT 0x51
#define SCMD_GET_PORT 0x52
#define SCMD_RESET 0x61
#define SCMD_LCD_OUTSTR 0x71
#define SCMD_LCD_RESET 0x72
#define SCMD_LCD_SETXY 0x73
#define SCMD_LCD_SETLINE 0x74
#define SCMD_LCD_CLEAR 0x75
#define SRESP_GET_PORT_ERROR 0x41
#define SRESP_SET_PORT_ERROR 0x42
#define HEART_BEAT_INTERVAL 200 // Heartbeat interval X / 1000 seconds
unsigned int heart_beat_timer = HEART_BEAT_INTERVAL;
unsigned int last_jiffies=0;
void main(){
Delay400Ms(); // Startup wait, wait for LCM to enter working state
LCMInit(); // LCM Initialization
Delay5Ms(); // Delay a moment (can be omitted)
mychar(10,1); // Display custom character
init_serialcomm();
P0=0x0ff;
P2=0x00;
sys_init();
//send_string_com("ok",2);
//lcd_reset();
//lcd_power_on();
//lcd_self_test();
while(1){
if (jiffies - last_jiffies >= 20){// Each interrupt is 50us, so it takes 20 times to be 1ms
last_jiffies = jiffies;
heart_beat_timer--;
if (send_delay)
send_delay--;
}
if (heart_beat_timer == 0){
heart_beat_timer = HEART_BEAT_INTERVAL;
while(1) {recv();if (recv_stat == RECV_SUCCESS)
{
P0_0=~P0_0;
send_string_com(recv_buf,strlen(recv_buf));
Display_T();
recv_stat = 0;break;}
recv_stat = 0;
}
}
/*#if 0
if (send_stat == 0){
// Collision test
START_SEND(8);
send_buf[1]='T';
send_buf[2]='e';
send_buf[3]='s';
send_buf[4]='t';
send_buf[5]='O';
send_buf[6]='k';
send_buf[7]='!';
lcd_out_string("sending:");
//send_string_com(send_buf,strlen(send_buf));
//printhex(send_buf[0]);
//printhex(send_buf[1]);
}
#endif
*/
wirless();
if (send_stat == SEND_FAILED){
send_stat = 0;
}else if (send_stat == SEND_SUCCESS){
send_stat = 0;
P2_3=~P2_3;
}
//recv();
//send_string_com("start",5);
/*while(1) {recv();if (recv_stat == RECV_SUCCESS)
{
P0_0=~P0_0;
send_string_com(recv_buf,strlen(recv_buf));} }
*/
/* if (recv_stat == RECV_SUCCESS){
//send_string_com("test1",5);
#if 1
//unsigned int i;
//for(i=0; i<recv_byts; i++)
// serial_out(recv_buf[i]); // Output received character
P0_0=~P0_0;
send_string_com(recv_buf,strlen(recv_buf));
#else
//if (recv_buf[1]=='o')
//P0=0x00;
//lcd_out_string("data received:");
//printhex(recv_buf[0]);
//printhex(recv_buf[1]);
//OutChar('\n');
//send_string_com("test3",5);
#endif
recv_stat = 0;
}
*/
#if 0
if (RI){
unsigned char scmd[17];
heart_beat_timer = HEART_BEAT_INTERVAL;
wait_serial(scmd, 1, 0);
switch(scmd[0]){
case SCMD_RESET:
((void (code *) (void))0x0000) ();// Software reset
case SCMD_SET_PORT:
if (wait_serial(scmd, 2, 200))
break;
switch(scmd[0]){
case 0:
P0 = scmd[1];
break;
case 1:
P1 = scmd[1];
break;
case 2:
P2 = scmd[1];
break;
case 3:
P3 = scmd[1];
break;
}
break;
case SCMD_GET_PORT:
if (wait_serial(scmd, 1, 200))
break;
switch(scmd[0]){
case 0:
serial_out(P0);
break;
case 1:
serial_out(P1);
break;
case 2:
serial_out(P2);
break;
case 3:
serial_out(P3);
break;
}
break;
case SCMD_LCD_OUTSTR:
if (wait_serial(scmd, 1, 200))
break;
scmd[scmd[0]] = 0;
if (wait_serial(scmd, scmd[0], 200))
break;
lcd_out_string(scmd);
break;
case SCMD_LCD_RESET:
lcd_reset();
break;
case SCMD_LCD_CLEAR:
lcd_clear();
break;
case SCMD_LCD_SETXY:
if (wait_serial(scmd, 2, 200))
break;
SetXY(scmd[0], scmd[1]);
break;
case SCMD_LCD_SETLINE:
if (wait_serial(scmd, 1, 200))
break;
SetLine(scmd[0]);
break;
default:
break;
}
}
#endif
}
}
To help everyone learn better, Changxue Electronics Network has specially added a WeChat public account for microcontrollers and EDA, which pushes related knowledge every day. I hope it can help your studies!