Linux应用笔记--vi


问:有什么简单的方法可以产生一组随机字符串?
答:让新手退出vi.


基本命令:

保存退出
:wq

不保存退出
:q!

保存不退出
:w

跳到第100行
:100

查找指定字符串:
:/str1
查找下一个:
n
查找上一个:
shift + n

复制当前行:
yy
粘贴复制行:
p

从本行向下复制3行:
y ↓ 2
从本行向上复制3行:
y ↑ 2

撤销最近一次操作:
u
撤销本行操作:
shift + u

sed格式:

:[address]s/pattern/replacement/flag
flag: g表示该行全部匹配项,无此选项,仅替换第1个匹配项

将第3行中所有的str1替换成str2

:3 s/str1/str2/g

将全文中所有的str1替换成str2

%s/LED/KEYS/g
或者:
:g/str1/s//str2/g
第1个g表示所有行,第2个g表示每行所有匹配

删除空白行: 删除只有空格或制表符内容的行

:g/^[\ '\t']*$/d

删除空行: 什么内容都没有

:g/^$/d

- 阅读全文 -

LwIP应用笔记--UDP应用


UDP通信

首选创建一个PCB块

struct udp_pcb* upcb;
upcb = udp_new();
// 绑定本地端口
udp_bind(upcb, IP_ADDR_ANY, 1234); 
// 连接远程端口(可省略)
udp_connect(upcb, &Remote, 5555);

UDP发送:

struct pbuf *p; 
// 在POOL中分配pbuf空间(无操作系统时一般用POOL)
p = pbuf_alloc(PBUF_TRANSPORT, Len, PBUF_POOL);    
if(p)
{    
    // 复制需要发送的数据到pbuf */
    pbuf_take(p, buff, len);

    // 发送数据至绑定的地址和端口    
    upd_send(upcb, p);    
    // 发送数据到指定地址和端口    
    udp_sendto(upcb, p, ipaddr, port);        
    // 指定网卡发送数据     
    udp_sendto_if(upcb, p, ipaddr, port, netif); 
}

// 释放pbuf空间(重要)
pbuf_free(p);   

UDP接收:

// 首先声明接收回调函数
void udp_recv_callback(void* arg,      // udp_recv的第3个参数
                struct udp_pcb* upcb,  // 本机描述符
                struct pbuf *p,        // 接收数据
                struct ip_addr *addr,  // 发送端IP
                uint16_t port)         // 发送端口
{
  // 将接收到的数据原路返回
  udp_sendto(upcb, p, &ipaddr, port);

  // 重要:回调函数的数据是动态申请的,一定要释放
  pbuf_free(p); 
}

// UPD接收到数据时,会调用回调函数处理,如果需要传入参数,
// 则通过第3个参数传入指针
udp_recv(upcb, udp_recv_callback, NULL);
    

重新设置IP:

// 修改网络参数前,先禁用网卡    
netif_set_down(netif);  

netif_set_ipaddr(netif,  &ipaddr);  // 设置IP地址
netif_set_netmask(netif, &netmask); // 设置子网掩码
netif_set_gw(netif, &gateway);      // 设置网关
 
// 设置全部参数(与上边的操作选一种)
// netif_set_addr(netif, &ipaddr, &netmask, &gateway);

// 修改完成后,重新启动网卡     
netif_set_up(netif);    

组播

发送组播: 发送不需要特殊设置,只需要向目地地址设置为组播地址即可。
组播地址取值范围:224.0.0.0~239.255.255.255

接收组播:

修改协议栈使能组播功能

// opt.h
#ifndef LWIP_IGMP
#define LWIP_IGMP    1
#endif

// 添加随机接口
#include <stdlib.h>
#define LWIP_RAND() rand()

注意事项:
需要使能网卡驱动中的组播功能。

示例代码:

ip_addr_t group;
IP4_ADDR(&group, 224,1,1,2);    // 组播号(D类IP地址)  

// 加入组播分组
igmp_joingroup(IP_ADDR_ANY,(struct ip_addr *)(&group));   
// igmp_joingroup(&local_ip,(struct ip_addr *)(&group));

// 脱离组播分组    
igmp_leavegroup(IP_ADDR_ANY, &group);   

- 阅读全文 -

Linux应用程序--CAN总线


文章摘要:本文描述了关于CAN总线应用程序的编程。
内核版本:linux-3.8.13
硬件平台:AM335x


内核配置: 添加CAN驱动程序及协议

[*] Networking support --->
    <*> CAN bus subsystem support  --->
        <*> Raw CAN Protocol (raw access with CAN-ID filtering)
        <*> Broadcast Manager CAN Protocol (with content filtering)
            CAN Device Drivers  --->
                <*> Bosch D_CAN devices  --->
                    <*>   Generic Platform Bus based D_CAN driver

系统设置:命令及说明

配置CAN总线参数

# ip link set can0 type can bitrate 500000 triple-sampling on

或者

# canconfig can0 bitrate 500000 ctrlmode triple-sampling on

bitrate参数用于设置波特率,此处设置为500K bps.

使能CAN总线接口

# ip link set can0 up

或者

# canconfig can0 start 

此命令完成后,可通过ifconfig查看到相关接口。

关闭CAN总线接口

# ip link set can0 down

或者

# canconfig can0 stop

示例代码:

/*
 * 初始化CAN控制器
 */
int can_open(char* name)
{
    int fd;
    struct ifreq can_ifr;
    struct sockaddr_can can_addr; 
    // int flag = 1; 
       
    // 初始化socket套接字用于CAN设备
    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);     
            
    strcpy(can_ifr.ifr_name, name);     
    ioctl(fd, SIOCGIFINDEX, &can_ifr);        // 指定can设备   
      
    can_addr.can_family  = AF_CAN;            // 指定协议族
    can_addr.can_ifindex = can_ifr.ifr_ifindex;  
             
    bind(fd, (struct sockaddr *)&can_addr, sizeof(can_addr)); // 绑定
    //ioctl(fd, FIONBIO, &flag);        //设置为非阻塞模式  
    return fd;  
}
/*
 *  向CAN总线发送数据
 */
int can_send(int can, int id, unsigned char* buff)
{
    int ret; 
    struct can_frame can_frm = {0};
    
    can_frm.can_id  = id;      
    can_frm.can_dlc = 8;  
    memcpy(can_frm.data, buff, 8);
    
    ret = write(can, &can_frm, sizeof(can_frm));    
    if(ret != sizeof(can_frm)) 
    {   
        printf("can send error: id = %X\r\n", id);  
    }

    return 0;
}
/*
 *  向CAN总线读取数据
 */
int can_recv(int can, struct can_frame* pcf)
{
    int rxlen;
    
    // 正常情况下返回值为16(struct can_frame的长度)
    rxlen = read(can, pcf, sizeof(struct can_frame));
    if(rxlen != sizeof(struct can_frame))    
    {           
        return -1;    // 读取失败
    }

    return 0;
}

- 阅读全文 -

Linux应用程序--AMR与MP3解码


AMR,全称是:Adaptive Multi-Rate,自适应多速率,是一种音频编码文件格式,专用于有效地压缩语音频率,用于移动设备的音频压缩,压缩比非常高,但是音质比较差,主要用于语音类的音频压缩,不适合对音质要求较高的音乐类音频的压缩。


- 阅读全文 -

Linux应用程序--ALSA编程


文章摘要:
稍后抄一些关于alsa的介绍补充

运行环境:debian8


安装alsa应用程序接口库:

编译选项: -lasound


打开并初始化设备:

snd_pcm_t *handle;      
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t frames = 64;       // 每帧字节数
unsigned int sample      = 44100;    // 采样率(重要)
unsigned int channels    = 1;        // 通道数量

int alsa_init(void) 
{
    int ret;    
    
    // 打开音频设备
    ret = snd_pcm_open(&handle,
                       "default",
                       SND_PCM_STREAM_PLAYBACK,
                       0);
    if(ret)
    {
        perror("can not open pcm device "); 
    }
    
    // 分配内存
    snd_pcm_hw_params_alloca(&params);        
    // 填充默认参数
    snd_pcm_hw_params_any(handle, params);
    
    // 初始化访问权限
    //ret = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    //if (ret < 0) {
    //  perror("snd_pcm_hw_params_set_access");
    //}
            
    // 设置数据格式
    // SND_PCM_FORMAT_S16_LE
    // SND_PCM_FORMAT_S24_LE
    snd_pcm_hw_params_set_format(handle, 
                                 params,
                                 SND_PCM_FORMAT_U8);         
    // 设置通道数量
    snd_pcm_hw_params_set_channels(handle, params, 1);    
    
    // 设置采样率(重要)
    snd_pcm_hw_params_set_rate_near(handle, 
                                    params,
                                    &sample, 
                                    0);        
    // 设置每帧的字节数        
    snd_pcm_hw_params_set_period_size_near(handle,
                              params, 
                              &frames, 
                              0);    
    // 将参数写入设备
    ret = snd_pcm_hw_params(handle, params);    

    return 0;
}

播放WAV格式:

int main(int argc, char** argv)
{        
    int fd;
    int ret;
    char buff[100];
        
    fd = open(argv[1], O_RDONLY);
    if(fd < 0)
    {
        perror("can not open snd file ");   
    }

    ret = read(fd,buff,44);        // 读取文件头并解析相关参数 
    // 处理参数   
    alsa_init();      // 初始化声卡
        
    printf("start read\r\n");
    while(1)
    {
        ret = read(fd,buff,64);    // 从文件读入声音数据
        if(ret <= 0)
        {
            break;  
        }            
        ret = snd_pcm_writei(handle, buff, 64);  // 将数据写入alsa播放             
        if (ret == -EPIPE)
        {
            fprintf(stderr, "underrun occurred\n");
            snd_pcm_prepare(handle);
        } 
    }
    
    close(fd);                 // 关闭文件  
    snd_pcm_drain(handle);     
    snd_pcm_close(handle);     // 关闭ALSA    
}

- 阅读全文 -


Copyright©2018 春天花会开, All Rights Reserved. Email: webmaster@oroct.com