加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入

C学习-信息转换为PUD格式发送短信(限英文)

03/20 15:11
2791
服务支持:
技术交流群

完成交易后在“购买成功”页面扫码入群,即可与技术大咖们分享疑惑和经验、收获成长和认同、领取优惠和红包等。

虚拟商品不可退

当前内容为数字版权作品,购买后不支持退换且无法转移使用。

加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论
放大
实物图
相关方案
  • 方案介绍
    • 前言
    •  一、演示效果
    • 二、模块
    • 三、代码编写
    •  四、参考
  • 相关文件
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

前言

因为之前做项目的时候,每次使用短信模块发送短信都需要在平台去转换一次数据,搞的相当麻烦,所以就尝试这可以写一共PUD格式转换的文件来在程序中让他自动就转换成功,

**  转载请注明出处

 一、演示效果

1. 参数定义

2. STM32串口输出

 3. 平台验证

PDU转换器icon-default.png?t=N7T8http://smstools3.kekekasvi.com/topic.php?id=288

二、模块

开发版的话还是用到的STM32系列,首先使用到的模块的话 也在我之前提到的一个联网模块,支撑GPRS和GSM功能,用来学习再适合不过了,我就直接丢篇博客了

嵌入式外设集 -- GSM+GPRS联网模块(GA6-B)icon-default.png?t=N7T8https://blog.csdn.net/herui_2/article/details/130560784?spm=1001.2014.3001.5502

三、代码编写

1. C 程序验证代码

该程序可以将电话号码和文本消息数据编码为发送到手机的协议数据单元(PDU)格式。主功能体现在`to_pdu`函数,它处理电话号码反转和Unicode数据转换,然后将这些组合成PDU字符串。如果编码成功,它将输出PDU的长度和内容;如果失败,则输出失败信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 判断输入字符串是否全部为数字字符。
int is_numeric(const char *input) {
    while (*input) {
        // 如果当前字符不是数字,则返回0(假)。
        if (!isdigit((unsigned char) *input)) return 0;
        input++;
    }
    // 如果所有字符都是数字,则返回1(真)。
    return 1;
}

// 将电话号码中每两位字符进行反转。
char *two_bit_inversion(const char *phone) {
    // 如果输入字符串包含非数字字符,则返回NULL。
    if (!is_numeric(phone)) return NULL;
    size_t len = strlen(phone);
    // 为反转后的电话号码分配内存。额外的空间是给'F'和'�'的。
    char *inverted_phone = malloc(len + 1 + (len % 2));

    if (inverted_phone == NULL) return NULL;

    // 如果电话号码的长度为奇数,则添加一个'F'。
    if(len % 2 == 1) {
        strcat(strcpy(inverted_phone, phone), "F"); // 如果长度为奇数,则在末尾加上'F'
    } else {
        strcpy(inverted_phone, phone);
    }

    // 在字符串中交换相邻字符的位置。
    for(size_t i = 0; i < len; i += 2) {
        char tmp = inverted_phone[i];
        inverted_phone[i] = inverted_phone[i + 1];
        inverted_phone[i + 1] = tmp;
    }

    return inverted_phone;
}

// 将输入字符串转换为Unicode字符串。
void string_to_unicode(const char *input, char *output) {
    while (*input) {
        // 将输入字符串的每个字符转换为Unicode,并存储在输出字符串中。
        sprintf(output, "%04X", (unsigned char)*input++);
        output += 4;
    }
}

// 从电话号码和数据中构建PDU(协议数据单元)字符串。
char *to_pdu(const char *phone, const char *data) {
    // 利用two_bit_inversion函数转换电话号码。
    char *pdu_phone = two_bit_inversion(phone);
    // 如果转换失败,则返回NULL。
    if (!pdu_phone) return NULL;

    size_t len = strlen(data);
    char unicode_data[len * 4 + 1];
    // 将数据转换为Unicode编码。
    string_to_unicode(data, unicode_data);

    // 计算PDU消息中数据的长度。
    int data_length = strlen(unicode_data) / 2;
    // 计算PDU消息的总长度。
    size_t pdu_length = strlen("0011000D9168") + strlen(pdu_phone) + strlen("0008FF") + 2 + strlen(unicode_data) + 1;
    char *message = malloc(pdu_length);

    // 如果消息分配失败,则释放电话号码内存并返回NULL。
    if (message == NULL) {
        free(pdu_phone);
        return NULL;
    }

    // 构建PDU消息。
    sprintf(message, "0011000D9168%s0008FF%02X%s", pdu_phone, data_length, unicode_data);

    // 释放电话号码内存。
    free(pdu_phone);
    // 返回PDU消息字符串。
    return message;
}

int main() {
    const char *phone = "15883813998";
    const char *data = "999999";

    // 调用to_pdu函数并打印结果。
    char *pdu = to_pdu(phone, data);
    if (pdu) {
        // 打印NUM,表示PDU的长度。
        printf("NUM %dn", strlen(pdu)/2-1);
        // 打印PDU。
        printf("PDU: %s", pdu);

        // 使用完后记得释放内存。
        free(pdu);
    } else {
        // 如果编码PDU失败,则打印失败信息。
        printf("Failed to encode PDU.n");
    }

    return 0;
}

2. STM32移植

main.c

移植的时候需要注意,这个C代码再keil环境里面是跑不成功的,需要在 VSCode 或者其他编译器继续编译生成hex文件,代码本身没有问题,只是keil不能格式兼容。

pdu.c

#include "pdu.h"

// 判断输入字符串是否全部为数字字符。
int is_numeric(const char *input)
{
    while (*input)
    {
        // 如果当前字符不是数字,则返回0(假)。
        if (!isdigit((unsigned char)*input))
            return 0;
        input++;
    }
    // 如果所有字符都是数字,则返回1(真)。
    return 1;
}

// 将电话号码中每两位字符进行反转。
char *two_bit_inversion(const char *phone)
{
    int len;
    char *inverted_phone;
    int i;
    char tmp;

    // 如果输入字符串包含非数字字符,则返回NULL。
    if (!is_numeric(phone))
        return NULL;
    len = strlen(phone);
    // 为反转后的电话号码分配内存。额外的空间是给'F'和'�'的。
    inverted_phone = malloc(len + 1 + (len % 2));

    if (inverted_phone == NULL)
        return NULL;

    // 如果电话号码的长度为奇数,则添加一个'F'。
    if (len % 2 == 1)
    {
        strcat(strcpy(inverted_phone, phone), "F"); // 如果长度为奇数,则在末尾加上'F'
    }
    else
    {
        strcpy(inverted_phone, phone);
    }

    // 在字符串中交换相邻字符的位置。
    for (i = 0; i < len; i += 2)
    {
        tmp = inverted_phone[i];
        inverted_phone[i] = inverted_phone[i + 1];
        inverted_phone[i + 1] = tmp;
    }

    return inverted_phone;
}

// 将输入字符串转换为Unicode字符串。
void string_to_unicode(const char *input, char *output)
{
    while (*input)
    {
        // 将输入字符串的每个字符转换为Unicode,并存储在输出字符串中。
        sprintf(output, "%04X", (unsigned char)*input++);
        output += 4;
    }
}

// 从电话号码和数据中构建PDU(协议数据单元)字符串。
char *to_pdu(const char *phone, const char *data)
{
    char *pdu_phone;
    int len;
    int data_length;
    int pdu_length;
    char *message;
    // 利用two_bit_inversion函数转换电话号码。
    pdu_phone = two_bit_inversion(phone);
    // 如果转换失败,则返回NULL。
    if (!pdu_phone)
        return NULL;

    len = strlen(data);
    char unicode_data[len * 4 + 1];

    // 将数据转换为Unicode编码。
    string_to_unicode(data, unicode_data);

    // 计算PDU消息中数据的长度。
    data_length = strlen(unicode_data) / 2;
    // 计算PDU消息的总长度。
    pdu_length = strlen("0011000D9168") + strlen(pdu_phone) + strlen("0008FF") + 2 + strlen(unicode_data) + 1;
    message = malloc(pdu_length);

    // 如果消息分配失败,则释放电话号码内存并返回NULL。
    if (message == NULL)
    {
        free(pdu_phone);
        return NULL;
    }

    // 构建PDU消息。
    sprintf(message, "0011000D9168%s0008FF%02X%s", pdu_phone, data_length, unicode_data);

    // 释放电话号码内存。
    free(pdu_phone);
    // 返回PDU消息字符串。
    return message;
}

pdu.h

#ifndef __PUD_H
#define __PUD_H
// C 库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 定义电话号码和消息(必须是英文)
int is_numeric(const char *input);
char *two_bit_inversion(const char *phone);
void string_to_unicode(const char *input, char *output);
char *to_pdu(const char *phone, const char *data);

#endif

3. Android 验证代码

就是通过朋友写的这个java文件,才有灵感去做的这个格式转换,这里也发给大家做个参考


object PduConvert {
    fun toPdt(phone: String, data: String): PduData? {
        val headers = "0011000D9168"
        val pduPhone = twoBitInversion(phone) ?: return null
        val unicodeData = stringToUnicode(data)
        val dataLength = (unicodeData.length / 2).toString(16).padStart(2, '0')
        val message =
            (headers + pduPhone + "0008FF" + dataLength + unicodeData).uppercase(Locale.getDefault())
        return PduData(data.length * 2 + 15, message)
    }

    private fun twoBitInversion(data: String): String? {
        var phone = data
        return if (isNumeric(phone)) {
            if (phone.length % 2 == 1) phone += "F"
            phone.chunked(2) // 每两位一组进行分割
                .joinToString("") { it.reversed() } // 每组内的字符翻转后拼接到一起
        } else
            null
    }

    private fun isNumeric(input: String): Boolean {
        val regex = Regex("""^d+$""")
        return regex.matches(input)
    }

    fun stringToUnicode(input: String): String {
        val stringBuilder = StringBuilder()
        for (char in input) {
            stringBuilder.append("u").append(char.toInt().toString(16).padStart(4, '0'))
        }
        return stringBuilder.toString().replace("u", "")
    }

    fun unicodeToString(input: String): String {
        val stringBuilder = StringBuilder()
        input.chunked(4).forEach {
            val charCode = Integer.parseInt(it, 16)
            stringBuilder.append(charCode.toChar())
        }
        return stringBuilder.toString()
    }
}

 四、参考

SMS短信的PDU编码规则icon-default.png?t=N7T8https://blog.csdn.net/zx249388847/article/details/52597990/?ops_request_misc=&request_id=&biz_id=102&utm_term=%E4%BF%A1%E6%81%AF%E8%BD%AC%E6%8D%A2%E4%B8%BAPUD%E6%A0%BC%E5%BC%8F%E5%8F%91%E9%80%81%E7%9F%AD%E4%BF%A1&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~sobaiduweb~default-5-52597990.nonecase&spm=1018.2226.3001.4450


请关注公众号进行获取和咨询


**  转载请注明出处

联系方式 微信号:13648103287

  • 联系方式.docx

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
PS2801-1-F3-A 1 NEC Electronics Group Transistor Output Optocoupler, 1-Element, 2500V Isolation,
$0.98 查看
TJA1055T/3/C,518 1 NXP Semiconductors TJA1055 - Enhanced fault-tolerant CAN transceiver SOIC 14-Pin

ECAD模型

下载ECAD模型
$1.64 查看
SST39VF6401B-70-4I-EKE-T 1 Microchip Technology Inc SST39VF6401B-70-4I-EKE-T
$4.41 查看

相关推荐

电子产业图谱

方案定制,程序设计方案、单片机程序设计与讲解、APP定制开发。本公众号致力于向读者传递关于程序设计和开发的相关知识,并分享一些关于软件开发的最佳实践。如果您有什么问题或建议,请随时联系我们。我们将竭诚为您服务