/**
******************************************************************************
* @file Project/main.c
* @author MCD Application Team
* @version V2.3.0
* @date 16-June-2017
* @brief Main program body
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stdio.h"
#include "string.h"
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
volatile uint16_t ms_counter = 0;
static uint8_t sec_count = 0;
uint8_t flag_1s = 0; // 1秒标志
uint8_t flag_30s = 0; // 30秒标志
uint8_t flag_pireq_received = 0; // 接收到PIREQ命令标志
uint8_t flag_brightness_received = 0; // 接收到亮度命令标志
uint8_t brightness = 56;
const char fixedMsg[] = "$PFEC,musts,1,306,29,1,2,60,64.0,1,4124,,,4661,,*71\r\n";
const char piresp1[] = "$PFEC,pidat,0,MU-190*69\r\n";
const char piresp2[] = "$PFEC,musts,1,306,29,1,2,60,64.0,1,4124,,,4661,,*71\r\n";
const char piresp3[] = "$PFEC,pidat,1,2651020-01.03*56\r\n";
const char piresp4[] = "$PFEC,pidat,3,001822*6E\r\n";
const char target_cmd[] = "$PFEC,pireq*43";
const char brightness_cmd_prefix[] = "$ECDDC,,"; // 亮度控制命令前缀
#define RX_BUF_SIZE 64
char rx_buf[RX_BUF_SIZE];
uint8_t rx_index = 0;
// 时钟配置 (内部16MHz HSI)
void CLK_Config(void) {
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 16MHz
}
// 计算NMEA校验和
uint8_t calculateChecksum(const char* data) {
uint8_t crc = 0;
while (*data) {
crc ^= *data++;
}
return crc;
}
// UART1配置 (9600 8N1)
void UART1_Config(void) {
UART1_DeInit();
UART1_Init(
4800, // 波特率
UART1_WORDLENGTH_8D, // 8位数据
UART1_STOPBITS_1, // 1位停止
UART1_PARITY_NO, // 无校验
UART1_SYNCMODE_CLOCK_DISABLE, // 异步模式
UART1_MODE_TX_ENABLE // 使能发送
);
UART1_Cmd(ENABLE);
}
// TIM4配置 (1ms中断)
void TIM4_Config(void) {
TIM4_TimeBaseInit(TIM4_PRESCALER_128, 125); // 16MHz/128=125kHz, 125分频=1ms
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4_Cmd(ENABLE);
}
// TIM2配置 (2kHz PWM)
void TIM2_Config(void) {
// 配置PD3为TIM2 CH2输出
GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
TIM2_TimeBaseInit(
TIM2_PRESCALER_8, // 16MHz/8=2MHz
1000 - 1 // 2MHz/1000=2kHz
);
// 配置通道2 PWM模式
TIM2_OC2Init(
TIM2_OCMODE_PWM1, // PWM模式1
TIM2_OUTPUTSTATE_ENABLE,
560, // 初始占空比56% (1000*0.56=560)
TIM2_OCPOLARITY_HIGH // 高电平有效
);
TIM2_OC2PreloadConfig(ENABLE);
TIM2_ARRPreloadConfig(ENABLE);
TIM2_Cmd(ENABLE);
}
void updatePWM(uint8_t brightness) {
// 确保亮度在1-99范围内
if (brightness < 1) brightness = 1;
if (brightness > 99) brightness = 99;
uint16_t duty_cycle = brightness * 10; // 计算占空比值 (0.01% * 1000 = 10, 10% * 1000 = 100, 99% * 1000 = 990)
TIM2_SetCompare2(duty_cycle); // 更新PWM占空比
}
// 发送字符串函数
void UART1_SendString(const char* str) {
while (*str) {
UART1_SendData8(*str++);
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
}
// 发送亮度状态信息
void sendBrightnessStatus(uint8_t brightness) {
char temp[20];
uint8_t cs;
// 生成状态信息: $IIDDC,,<brightness>,,R*<checksum>\r\n
sprintf(temp, "IIDDC,,%u,,R", brightness);
cs = calculateChecksum(temp);
sprintf(temp, "$%s*%02X\r\n", temp, cs);
UART1_SendString(temp);
}
// 解析亮度控制命令
uint8_t parseBrightnessCommand(const char* cmd) {
// 命令格式: $ECDDC,,<brightness>,,C*<checksum>
uint8_t cmd_brightness;
uint8_t expected_checksum, actual_checksum;
char temp[RX_BUF_SIZE];
if (strlen(cmd) < 15 || cmd[0] != '$') // 检查命令长度和格式
return 0;
if (sscanf(cmd + strlen(cmd) - 4, "*%02X", &expected_checksum) != 1) // 提取校验和部分 (最后2个字符)
return 0;
// 计算实际校验和 (不包括$和*后面的部分)
const char* checksum_start = cmd + 1; // 跳过$
const char* checksum_end = strchr(cmd, '*');
if (!checksum_end) return 0;
// 复制待校验部分
uint8_t len = checksum_end - checksum_start;
if (len >= sizeof(temp)) return 0;
strncpy(temp, checksum_start, len);
temp[len] = '\0';
actual_checksum = calculateChecksum(temp);
// 校验和验证
if (actual_checksum != expected_checksum)
return 1;
// 提取亮度值
if (sscanf(cmd, "$ECDDC,,%hhu,,C", &cmd_brightness) != 1)
return 0;
// 确保亮度值在有效范围内
if (cmd_brightness < 1 || cmd_brightness > 99)
return 0;
// 更新亮度值
brightness = cmd_brightness;
return 1;
}
// TIM4中断服务程序 (1ms定时)
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) {
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
if (++ms_counter >= 1000) { // 1秒到达
ms_counter = 0;
flag_1s = 1;
if (++sec_count >= 30) { // 30秒到达
sec_count = 0;
flag_30s = 1;
}
}
}
// UART1接收中断服务程序
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18) {
char c = UART1_ReceiveData8(); // 读取接收到的字符
// 处理缓冲区溢出
if (rx_index >= RX_BUF_SIZE - 1) {
rx_index = 0; // 缓冲区溢出,重置
}
rx_buf[rx_index++] = c; // 存储字符
// 检查是否收到完整命令 (以换行符结束)
if (c == '\n') {
rx_buf[rx_index] = '\0'; // 终止字符串
if (strstr(rx_buf, target_cmd) != NULL) { // 检查是否收到PIREQ命令
flag_pireq_received = 1;
}
else if (strstr(rx_buf, brightness_cmd_prefix) != NULL) { // 检查是否收到亮度控制命令
flag_brightness_received = 1;
}
rx_index = 0; // 重置接收缓冲区
}
}
void main(void)
{
/* Infinite loop */
char temp[20];
uint8_t cs;
CLK_Config();
UART1_Config();
TIM2_Config();
TIM4_Config();
rx_index = 0;
rx_buf[0] = '\0';
// 启用全局中断
rim();
while (1)
{
if (flag_pireq_received) {
flag_pireq_received = 0;
// 发送4条响应消息
UART1_SendString(piresp1);
UART1_SendString(piresp2);
UART1_SendString(piresp3);
UART1_SendString(piresp4);
}
if (flag_brightness_received) {
flag_brightness_received = 0;
// 解析并更新亮度
if (parseBrightnessCommand(rx_buf)) {
// 更新PWM输出
updatePWM(brightness);
// 发送亮度状态信息
sendBrightnessStatus(brightness);
}
}
if (flag_1s) {
flag_1s = 0;
UART1_SendString(fixedMsg);
}
if (flag_30s) {
flag_30s = 0;
sprintf(temp, "IIDDC,,%u,,R", brightness);
cs = calculateChecksum(temp);
sprintf(temp, "$%s*%02X\r\n", temp, cs);
UART1_SendString(temp);
}
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
这是stm8S003F3P6的程序,帮我看看flash和ram大小合适吗