#include
#include
#include "me.h" //Custom general io simplification bit
void timer0_init(void);
void port_init(void);
void init(void);
void UART_init(void); //Serial port initialization program
void UART_rx(void); //Serial port receiving interrupt function
void send_text(unsigned char *s); //String sending function
void sendchar(unsigned char c); //Character sending function
void dog_init(void); //Initialize watchdog
unsigned char RX_data[4]={0}; //Data received by the serial port
unsigned char RX_counter=0; //Counter of bytes received by the serial port
unsigned char pwm1,pwm2,pwm3,pwm4,pwm5,pwm6,pwm7,pwm8,pwm9,pwm10,pwm11,pwm12,pwm13,pwm14,pwm15,pwm16,pwm17,pwm18,pwm19,pwm20; //20 pwm values respectively
unsigned char count; //pwm positioning variable
void main(void)
{
oSCCAL=0xAA; //System clock calibration, different chips and different frequencies
init(); //?
while(1)
{
WDR(); //Feed the dog desperately
if(RX_counter==4) //Receive a complete command message
{
RX_counter=0; // Clear the byte count counter received by the serial port
if((RX_data[0]==''''''''S'''''''')&&(RX_data[3]==''''''''E''''''''))//Judge whether the head and tail meet the requirements
{
CLI(); //Turn off interrupts and start judging data
switch(RX_data[1])
{
case 0x01:
pwm1=RX_data[2];
break;
case 0x02:
pwm2=RX_data[2];
break;
case 0x03:
pwm3=RX_data[2];
break;
case 0x04:
pwm4=RX_data[2];
break;
case 0x05:
pwm5=RX_data[2];
break;
case 0x06:
pwm6=RX_data[2];
break;
case 0x07:
pwm7=RX_data[2];
break;
case 0x08:
pwm8=RX_data[2];
break;
case 0x09:
pwm9=RX_data[2];
break;
case 0x0a:
pwm10=RX_data[2];
break;
case 0x0b:
pwm11=RX_data[2];
break;
case 0x0c:
pwm12=RX_data[2];
break;
case 0x0d:
pwm13=RX_data[2];
break;
case 0x0e:
pwm14=RX_data[2];
break;
case 0x0f:
pwm15=RX_data[2];
break;
case 0x10:
pwm16=RX_data[2];
break;
case 0x11:
pwm17=RX_data[2];
break;
case 0x12:
pwm18=RX_data[2];
break;
case 0x13:
pwm19=RX_data[2];
break;
case 0x14:
pwm20=RX_data[2];
break;
default:
SEI(); // Enable interrupt when error occurs so that error information can be sent
send_text("ER"); //If the range exceeds 20 pwm, the capital letter "ER" will be sent
break;
}
SEI(); //Restore interrupt enable
send_text("OK"); //Judge that the processing is complete and return ok;
}
}
}
}
void init(void)
{
CLI(); //disable all interrupts
port_init();
timer0_init();
TIMSK = 0x01; //Timer interrupt source
UART_init();
SEI(); //re-enable interrupts
}
void port_init(void)
{
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00;
DDRC = 0x7F;
PORTD = 0x00;
DDRD = 0xFF;
}
void send_char(unsigned char c) //Send single character function
{
while (!(UCSRA&(1 << UDRE))); //Judge whether the last transmission was completed
UDR = c; //Send data
}
#pragma interrupt_handler UART_rx: iv_USART_RX //Direct the serial port receive interrupt to UART_rx
/****************************************************** *******
Communication protocol: S+PWM?+Volue+E
Flag description: S: Header flag Hexadecimal: 0x53
Flag Description: PWM?: PWM number,? Range: 0x01~0x14 refers to 20 PWM outputs
Flag Description: Volue: PWM duty cycle, range 0x00~0xff, 0x00 if PWM is turned off
Flag description: E: End flag Hexadecimal: 0x45
Other instructions: A complete data occupies 4 bytes, and the first and last characters must be S and E respectively to be valid.
If the pwm bit exceeds 20, return the letter ER;
*************************************************** ******/
void UART_rx(void) //Serial port receive interrupt function
{
RX_data[RX_counter] = UDR;
if (RX_data[RX_counter]==''''''''S'''''''') //Correct misalignment and RX_counter overflow.
{
RX_data[0]=RX_data[RX_counter];
RX_counter=0;
}
RX_counter++; //Count the number of bytes received
}
void send_text(unsigned char *s) //String sending function
{
while (*s)
{
send_char(*s);
s++;
}
}
void UART_init(void) //Serial port initialization program
{
UCSRB = BIT(RXCIE)| BIT(RXEN) |BIT(TXEN); // Allow the serial port to send and receive, and respond to the receive completion interrupt
UBRR = 51; //Clock 8Mhz, baud rate 9600
UCSRC = BIT(URSEL)|BIT(UCSZ1)|BIT(UCSZ0); //8 bits of data + 1 stop bit
}
/**********************************************
Design idea: The servo typically requires a frequency of 20mS, that is, a frequency of 50Hz
In order to achieve 8-bit PWM accuracy, the 20mS time needs to be evenly divided into
256 copies, or 78.125 seconds, are defined with the target during an interrupt
The required pwm duty cycle value (pwm1~20) is compared to determine whether io should
Output 0 level, if not, output high level
Target interrupt time: 78.125uSec (plus 0.2% error)
Actual interruption time: 78.000uSec
If you want to increase the frequency, just modify the overflow time of the timer
If you want to increase the resolution of pwm, modify the value of count
*********************************************/
void timer0_init(void) //Timer initialization program
{
TCCR0 = 0x00; //Stop the timer
TCNT0 = 0xB4; //Set the initial value
TCCR0 = 0x02; //Start the timer
}
#pragma interrupt_handler timer0_ovf_isr:10 //Direct the timer overflow interrupt to timer0_ovf_isr, just like ORG in assembly
void timer0_ovf_isr(void) //Timer overflow interrupt program
{
TCNT0 = 0xB4; //Re-enter the initial value
count++; //Add 1 for each interrupt
if (count { portc5_1; }else{ //If not, output 0 portc5_0; } if (count { portc4_1; }else{ portc4_0; } if (count { portc3_1; }else{ portc3_0; } if (count { portc2_1; }else{ portc2_0; } if (count { portc1_1; }else{ portc1_0; } if (count { portc0_1; }else{ portc0_0; } if (count { portb5_1; }else{ portb5_0; } if (count { portb4_1; }else{ portb4_0; } if (count { portb3_1; }else{ portb3_0; } if (count { portb2_1; }else{ portb2_0; } if (count { portb1_1; }else{ portb1_0; } if (count { portd2_1; }else{ portd2_0; } if (count { portd3_1; }else{ portd3_0; } if (count { portd4_1; }else{ portd4_0; } if (count { portb6_1; }else{ portb6_0; } if (count { portb7_1; }else{ portb7_0; } if (count { portd5_1; }else{ portd5_0; } if (count { portd6_1; }else{ portd6_0; } if (count { portd7_1; }else{ portd7_0; } if (count { portb0_1; }else{ portb0_0; } } void dog_init(void) //Watchdog initialization { WDR(); //Watchdog count clear WDTCR=0x0F; //Enable the watchdog, and use 2048 frequency division, overflow time 2.1S at 5V } //Timer T0 interrupt, send control word and data to 8253 void T0Int() interrupt 1 { TH0 = 0xB1; TL0 = 0xE0; //20ms clock reference //Write the control word first, then write the count value SERVO0 = 0x30; //Select counter 0 and write control word PWM0 = BUF0L; //Write low first, then write high PWM0 = BUF0H; SERVO1 = 0x70; //Select counter 1 and write control word PWM1 = BUF1L; PWM1 = BUF1H; SERVO2 = 0xB0; //Select counter 2 and write control word PWM2 = BUF2L; PWM2 = BUF2H; }
Previous article:AVR Absolute Positioning Overview
Next article:AVR MCU Port Operation
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Do you know A2B, the automotive audio bus technology?
- SensorTile.Box becomes bricked after firmware upgrade
- Window Comparator
- [GD32L233C-START Review] Part 2 Compilation, Software Development Environment Review
- Stuck inexplicably
- Realization of Chinese Characters and Graphics Overlay Based on DSP
- How to install and use pressure transmitter
- The flashing prompt cannot recognize the device. What's going on?
- Model-Based Design and Its Embedded Implementation
- Q&A on Connectivity: Why Wi-Fi 6 Could Be Your Competitive Advantage